aboutsummaryrefslogtreecommitdiffstats
path: root/notes
diff options
context:
space:
mode:
Diffstat (limited to 'notes')
-rw-r--r--notes/coding_standard.rst427
-rw-r--r--notes/coding_standard.txt223
-rw-r--r--notes/dma.txt99
-rw-r--r--notes/exti.txt67
-rw-r--r--notes/pin-definitions.txt (renamed from notes/native-pin-definitions.txt)27
-rw-r--r--notes/portable.txt94
-rw-r--r--notes/timers.txt152
-rw-r--r--notes/usb.txt4
-rw-r--r--notes/vga.txt9
9 files changed, 700 insertions, 402 deletions
diff --git a/notes/coding_standard.rst b/notes/coding_standard.rst
new file mode 100644
index 0000000..f761db7
--- /dev/null
+++ b/notes/coding_standard.rst
@@ -0,0 +1,427 @@
+libmaple Coding Standards
+=========================
+
+Author: Marti Bolivar (mbolivar@leaflabs.com)
+
+LeafLabs team members are required to follow these when producing new
+code. Community contributors to libmaple are strongly encouraged to
+do so; following these rules will greatly increase the probability
+that your patches will be folded in.
+
+In general, do it like this unless there's a really good reason why
+not. You being lazy doesn't count as a good reason. Most, if not
+all, of these decisions are entirely arbitrary, but it's important for
+readability that we be consistent.
+
+The file ``.dir-locals.el`` in the libmaple root directory already
+ensures that many of these standards are followed by default in Emacs
+(but not on Windows, where it would need to be named
+``_dir_locals.el``, and no way, man). There's also some elisp
+scattered about this file which will provide you additional help.
+
+Vim customizations to do the same thing would be nice (hint, hint)!
+
+.. contents:: Contents
+ :local:
+
+License
+-------
+
+.. highlight:: scheme
+
+- Put an MIT license at the beginning of the file (look at any of our
+ source files for an example). Copyright should go either to you or
+ to LeafLabs, LLC.
+
+ Emacs: if you don't like seeing the license, you should use
+ elide-head (which will hide it for you). You can use the following::
+
+ (require 'elide-head)
+ (setq programming-mode-hooks '(c-mode-hook c++-mode-hook))
+ (add-to-list 'elide-head-headers-to-hide
+ '("The MIT License" . "DEALINGS IN\n [*] THE SOFTWARE"))
+ (add-to-list 'elide-head-headers-to-hide
+ '("The MIT License" . "DEALINGS IN THE\n...SOFTWARE"))
+ (dolist (hook programming-mode-hooks)
+ (add-hook hook (lambda () (elide-head))))
+
+Whitespace/Indentation
+----------------------
+
+- 4 space indents. [Set in ``.dir-locals.el``]
+
+- Unix newlines. [Some exceptions are currently grandfathered in;
+ these will go away in time.]
+
+- No tab characters. [Set in ``.dir-locals.el``]
+
+- No trailing whitespace. For help getting this (and no tab
+ characters) done automatically in Emacs, you can use this:
+
+ http://github.com/mbolivar/code-fascism
+
+ I hear tell you can get something similar in Vim; ask around, I
+ guess.
+
+- Files end in exactly one newline. [The presence of a newline at EOF
+ is already done by ``c-require-final-newline`` in recent versions of
+ Emacs.]
+
+- Exactly two newlines separate source paragraphs (you do separate
+ your code into paragraphs, don't you?).
+
+- The first line in a function is non-blank.
+
+.. highlight:: cpp
+
+- Exactly one space after ``if``, ``else``, ``for``, and ``while``,
+ before the following ``{`` or ``(``. One space before ``else``,
+ after the preceding ``}``. For example::
+
+ // This is good; we like this:
+ if (foo) {
+ while (quux) {
+ bar();
+ }
+ } else {
+ baz();
+ }
+
+ // THIS IS BAD! DON'T DO THIS:
+ if(foo){
+ while(quux){
+ bar();
+ }
+ }else{
+ baz();
+ }
+
+- Exactly one space in between binary arithmetic, logical, and
+ comparison operators and their operands. This doesn't apply to the
+ . and -> operators. Examples::
+
+ // This is good:
+ int x = a + b * (c - d);
+ if (x != 0 && a > 7) {
+ SerialUSB.println(x);
+ }
+
+ // THIS IS BAD!
+ int x = a+b*(c-d);
+ if (x!=0 && a>7) {
+ SerialUSB.println(x);
+ }
+
+ // This is good:
+ uint32 adc_data = ADC1_BASE->DR;
+ SerialUSB.println(adc_data);
+
+ // THIS IS BAD!
+ uint32 adc_data = ADC1_BASE -> DR;
+ SerialUSB . println(adc_data);
+
+- No space between a unary operator and its operand. Examples::
+
+ // Good:
+ x++;
+
+ // BAD!
+ x ++;
+
+ // Good:
+ y = -x;
+
+ // BAD!
+ y = - x;
+
+- If you need to break up a long line:
+
+ * Prefer to break up long expressions after a binary operator. Example::
+
+ // Good:
+ if (some_really_long_conditional_wow_this_really_goes_on_forever ||
+ maybe_something_else_could_happen_too) {
+ ...
+ }
+
+ // BAD!
+ if (some_really_long_conditional_wow_this_really_goes_on_forever
+ || maybe_something_else_could_happen_too) {
+ ...
+ }
+
+ * When breaking up a function's arguments over multiple lines, align
+ the arguments on subsequent lines with the first argument.
+ Example::
+
+ // Good:
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+ // BAD!
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+ // BAD!
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+- In function invocations, no space in between the function name and
+ the opening parenthesis. Example::
+
+ // Good:
+ SerialUSB.println("Hello, world!");
+
+ // BAD!
+ SerialUSB.println ("Hello, world!");
+
+- Don't indent C code within a conditionally-compiled ``extern "C"``
+ block. Example::
+
+ // Good:
+ #ifdef __cplusplus
+ extern "C"{
+ #endif
+
+ void some_c_function(void);
+
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+
+ // BAD!
+ #ifdef __cplusplus
+ extern "C"{
+ #endif
+
+ void some_c_function(void);
+
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+
+.. highlight:: scheme
+
+ Emacs does the "bad" behavior by default, which can be very
+ annoying. You can turn this off with::
+
+ (defun c-mode-inextern-lang-hook ()
+ (setcdr (assq 'inextern-lang c-offsets-alist) '-))
+ (add-hook 'c-mode-hook c-mode-inextern-lang-hook)
+
+Comments
+--------
+
+.. highlight:: c++
+
+- Multi-line comments are pretty flexible. Any of these is fine::
+
+ /* Comment starts here.
+ * Continued lines have a '*' before them.
+ * The comment can end after the last line.
+ */
+
+ /* Comment starts here.
+ * The comment can end on the same line. */
+
+ /*
+ * You can also place a newline after the opening "/*".
+ */
+
+- Doxygen comments are multi-line comments that begin with ``/**``
+ instead.
+
+- Single-line comments on the same line are ``//`` in C++. (That's OK
+ in C as well).
+
+- Single-line comments on their own source line should be ``/* */`` in
+ C, but can also be ``//`` in C++. (This isn't of great importance).
+ In Emacs, you can use M-; (comment-dwim), and it'll Do What You
+ Mean.
+
+Braces
+------
+
+- Mostly 1TBS:
+
+ http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS
+
+ The only difference is that the opening brace of a function's
+ definition occurs exactly one space character after the closing
+ parenthesis in that function's parameter list. Example::
+
+ void func(void) {
+ ...
+ }
+
+Naming conventions
+------------------
+
+There's always a fight about upper and lower case vs. underscores.
+We'll handle this as follows.
+
+- First, ``Dont_Mix_Like_This``, because ``It_Looks_Really_Ugly``, ok?
+ [There's been some debate about this, and some exceptions are
+ already grandfathered in, so in order to settle it, let's call this
+ a "recommendation" instead of "requirement".]
+
+- Variables: Use underscores to separate words in C identifiers::
+
+ int some_example_name;
+
+ User-facing C++ variables should be camel cased
+ (``thisIsAnExample``, ``boardPWMPins``, etc.), for consistency with
+ the Arduino style. It's probably a good idea for you to case
+ non-user facing C++ variables in the C style; this will help
+ disambiguate what's part of the Wirish API and what's not.
+
+- Classes: Pascal case. So ``ThisIsAClassName``, but ``thisIsNot``,
+ ``this_is_not``, and like I said,
+ ``Dont_You_DareTryANYTHING_STUPID``.
+
+- Functions: C functions are all lowercase, and words are separated by
+ underscores. C++ method names are camel cased.
+
+- Structs: Usually like variables (``adc_dev``, ``adc_reg_map``,
+ etc.), but it's not crucial. Don't feel obliged to put ``_t`` at
+ the end of the type name; we don't.
+
+- Macros and constants: all caps, separated by underscores. C++
+ variables with the ``const`` qualifier generally aren't considered
+ "constants" for the purposes of this rule; i.e., they are cased
+ according to the rules for variables. We make an exception for
+ ``PIN_MAP``, because it's the central Wirish data structure.
+
+- foo.h gets ``#ifdef``\ 'ed to ``_FOO_H_``.
+
+- Acronyms: The case of letters in an acronym is determined by the
+ case of the first letter in the acronym, which is determined by
+ following the above rules. Examples::
+
+ // Good:
+ void usb_func() { ... }
+ void frob_usb_disc() { ... }
+ class SomethingUSB {
+ void usbInit();
+ void initUSB();
+ };
+
+ // BAD:
+ class BadUsb { ... }; // say "GoodUSB" instead
+ void swizzle_USB_disc() { ... } // say "swizzle_usb_disc" instead
+
+Documentation
+-------------
+
+- You **must** document your code. At a bare minimum, this means
+ Doxygen comments on every user-facing function and type.
+ Additionally, you need to individually document the fields and
+ enumerator values of ``struct``\ s and ``enum``\ s. See any
+ register map type's definition for an example.
+
+- For libmaple proper, you don't need comments for each register bit
+ definition (for now).
+
+- Doxygen comments generally just belong on types, functions,
+ etc. that are part of the public user-facing API. This generally
+ means that if there's ReST documentation for it under docs/source/,
+ it needs Doxygen comments, and that ReST should use Breathe to pull
+ that Doxygen comment out. (For more info on this, see docs/README).
+
+ There are some exceptions to this rule since Breathe isn't totally
+ mature yet and Sphinx's C++ domain is still in flux. In these
+ cases, document the code "manually" in ReST.
+
+ This should be avoided if at all possible, since it creates a
+ maintenance burden of documenting things in two places at once, and
+ makes it easier for documentation to go stale.
+
+ If you do have to document something manually, put a comment in the
+ source file informing future maintainers about it, so they'll pay
+ extra attention when making changes.
+
+- When adding peripheral support, it would be nice if you put
+ longer-form comments into the /notes/ directory, with a comment in
+ the corresponding .h file referring to it. See /libmaple/dac.h for
+ an example.
+
+ This lets us keep the source files relatively free of "introductory"
+ material, while allowing new readers a convenient starting point.
+ These longer-form notes also have a habit of turning into
+ user-facing documentation.
+
+- For libmaple proper (the pure C library under libmaple/); the
+ convention is to document any user-facing function at the point where
+ it is defined. In particular, this means you should document an
+ externally-linked function defined in a .c file in that .c file, not
+ in the header file where it is declared to the user.
+
+General Formatting
+------------------
+
+.. highlight:: scheme
+
+- Keep it 80-column clean. That means Emacs says the largest column
+ number=79. You should turn on column number mode to help you out:
+
+ (column-number-mode 1)
+
+ You can get more help from lineker-mode:
+
+ http://www.helsinki.fi/~sjpaavol/programs/lineker.el
+
+ Just put lineker.el somewhere in your load-path, and:
+
+ (require 'lineker)
+ (dolist (hook '(c-mode-hook c++-mode-hook))
+ (add-hook hook (lambda () (lineker-mode 1))))
+
+.. highlight:: cpp
+
+Language Features and Compiler Extensions
+-----------------------------------------
+
+- In libmaple proper, aim for C99 compatibility. Some GCC extensions
+ are OK, but let's not go crazy.
+
+- If you'd like to get code into libmaple which uses a GCC extension
+ not already in use elsewhere, ask a LeafLabs developer (or another
+ one, if you are one) what they think about it first.
+
+- Explicitly approved GCC extensions:
+
+ * ``asm volatile``:
+ http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
+
+ * ``Nested functions``:
+ http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
+
+- In wirish, generally be very conservative when using C++ features
+ that aren't part of C. We are forced to use C++ for Arduino
+ compatibility (and the general Arduino style of pretending that an
+ object is a library), but it's an angry beast, and we don't want to
+ provoke it. The mantra is "C with classes".
+
+- Explicitly approved C++ features:
+
+ * Initializers that aren't constant; e.g. the ``gpio_dev*`` values
+ in a ``PIN_MAP``.
+
+ * Default arguments: e.g., the timeout argument defaulting to 0
+ (meaning to wait forever) in ``waitForButtonPress()``.
+
+- Explicitly forbidden C++ features:
+
+ * Templates
+
+- C++ features that are conditionally allowed, but require explicit
+ approval from at least two libmaple developers (one of which may be
+ yourself):
+
+ * Operator overloading: Never allowed when it's just for style.
+ Potentially allowed when you're implementing a class that models a
+ mathematical structure, and you'd like to implement
+ e.g. ``operator+()``.
diff --git a/notes/coding_standard.txt b/notes/coding_standard.txt
deleted file mode 100644
index 5cb96c3..0000000
--- a/notes/coding_standard.txt
+++ /dev/null
@@ -1,223 +0,0 @@
-libmaple Coding Standards
-=========================
-
-Author: Marti Bolivar (mbolivar@leaflabs.com)
-
-LeafLabs team members are required to follow these when producing new
-code. Community contributors to libmaple are strongly encouraged to
-do so; following these rules will greatly increase the probability
-that your patches will be folded in.
-
-In general, do it like this unless there's a really good reason why
-not. You being lazy doesn't count as a good reason. Most, if not
-all, of these decisions are entirely arbitrary, but it's important for
-readability that we be consistent.
-
-The file .dir-locals.el in the libmaple root directory already ensures
-that many of these standards are followed by default in Emacs (but not
-on Windows, where it would need to be named _dir_locals.el, and no
-way, man). There's also some elisp scattered about this file which
-will provide you additional help.
-
-Vim customizations to do the same thing would be nice (hint, hint)!
-
-License
--------
-
-- Put an MIT license at the beginning of the file (look at any of our
- source files for an example). Copyright should go to either you or
- LeafLabs LLC.
-
- Emacs: if you don't like seeing the license, you should use
- elide-head (which will hide it for you). Here is some elisp you can
- modify to make this pleasant:
-
- (require 'elide-head)
- (setq programming-mode-hooks '(c-mode-hook c++-mode-hook))
- (add-to-list 'elide-head-headers-to-hide
- '("The MIT License" . "DEALINGS IN\n [*] THE SOFTWARE"))
- (add-to-list 'elide-head-headers-to-hide
- '("The MIT License" . "DEALINGS IN THE\n...SOFTWARE"))
- (dolist (hook mbolivar-programming-mode-hooks)
- (add-hook hook (lambda () (elide-head))))
-
-Whitespace/Indentation
-----------------------
-
-- 4 space indents. [Set in .dir-locals.el]
-
-- Unix newlines.
-
-- No tab characters. [Set in .dir-locals.el]
-
-- No trailing whitespace. For help getting this (and no tab
- characters) done automatically in Emacs, you can use this:
-
- http://github.com/mbolivar/code-fascism
-
- I hear tell you can get something similar in vim; ask around, I
- guess.
-
-- Files end in exactly one newline. [The presence of a newline at EOF
- is already done by `c-require-final-newline' in recent versions of
- Emacs.]
-
-- Exactly two newlines separate source paragraphs (you do separate
- your code into paragraphs, don't you?).
-
-- The first line in a function is non-blank.
-
-- Don't indent C code within a conditionally-compiled extern "C"
- block. Emacs does this by default, which can be very annoying; you
- can turn this behavior off with
-
- (defun c-mode-inextern-lang-hook ()
- (setcdr (assq 'inextern-lang c-offsets-alist) '-))
-
- (add-hook 'c-mode-hook c-mode-inextern-lang-hook)
-
-
-Comments
---------
-
-- Multi-line comments look like this:
-
- /* text starts here
- * continued lines have a '*' before them
- * the comment can end after the last line
- */
-
- or this:
-
- /* comment starts here
- * the comment can end on the same line */
-
-- Doxygen comments are newline comments that begin with /** instead.
- It is not required that the "/**" appear on a line by itself.
-
-- Single-line comments on the same line are // in c or c++.
-
-- Single-line comments on their own source line are /* */ in c, but
- can also be // in c++. If you think that typing out /* */ is too
- slow in emacs, use M-; (comment-dwim) when you're on an empty line,
- and it'll ... well...
-
- You should be using the (super awesome) comment-dwim; it pretty
- much does exactly what you want to the comment on the current
- line, including "create one and put it in the right place".
-
-Braces
-------
-
-- 1TBS. Nothing more need be said.
-
- http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS
-
-Naming conventions
-------------------
-
-- There's always a fight about upper and lower case vs. underscores.
- We'll handle this as follows.
-
- First, Dammit_Dont_Mix_Like_This, because It_Looks_Really_Ugly, ok?
- [There's been some debate about this, and some exceptions are
- already grandfathered in, so in order to settle it, let's call this
- a "recommendation" instead of "requirement".]
-
-- Variables: Use underscores to separate words in C identifiers:
-
- int some_example_name;
-
- It is strongly advised to do it this way in C++ too, but it's not
- [yet] mandatory.
-
-- Classes: Pascal case. So ThisIsAClassName, but thisIsNot,
- this_is_not, and like I said, Dont_You_DareTryANYTHING_STUPID.
-
-- Functions: C functions are all lowercase, and words are separated by
- underscores. C++ method names are camel cased (thisIsAnExample).
-
-- Structs: pick a style from "Variables" or "Classes" depending on how
- you mean it (since it might be either a simple record type, in which
- case do like c variables, or you might be faking an object in c, in
- which case do like classes). If it's in a typedef, don't feel
- obliged to put "_t" at the end of the name; we don't.
-
-- Macros and constants: all caps, separated by underscores. Variables
- with the "const" qualifier aren't considered "constants" for the
- purposes of this rule; i.e., case them according to the rules for
- variables.
-
-- foo.h gets #ifdef'ed to _FOO_H_.
-
-- Acronyms: The case of letters in an acronym is determined by the
- case of the first letter in the acronym, which is determined by
- following the above rules. Examples:
-
- void usb_func() { ... }
-
- class SomethingUSB {
- void usbInit();
- void initUSB();
- };
-
- Never do this:
-
- class BadUsb { ... }; // say "GoodUSB" instead
-
-Documentation
--------------
-
-- Document your code. This should go without saying.
-
-- For complicated peripherals, it would be nice if you put longer-form
- comments into this directory (notes/), with a comment in the
- corresponding .h file referring to it. See libmaple/dac.h for an
- example. That lets us keep the source files relatively clean while
- still allowing new readers to have a starting point.
-
-- At least put a doxygen comment with a nonempty @brief for every .h
- file you add. See the existing ones for examples. For now, it'd be
- better if you didn't put a @brief into any .c[pp] files, since it
- (currently) interferes with our documentation generator in a way
- that I won't explain here (though you can look into the LeafLabs or
- michaeljones breathe repos on github and potentially figure out
- why).
-
-- Doxygen comments generally just belong on types, functions,
- etc. that are part of the public user-facing API. This generally
- means that if there's ReST documentation for it under docs/source/,
- it needs Doxygen comments, and that ReST should use Breathe to pull
- that Doxygen comment out. (For more info on this, see docs/README).
-
- There are some exceptions to this rule since Breathe isn't totally
- mature yet and Sphinx's C++ domain is still in flux. In these
- cases, document the code "manually" in ReST.
-
- This should be avoided if at all possible, since it creates a
- maintenance burden of documenting things in two places at once, and
- provides an opportunity for bad documentation to slip in, when the
- code comments fall out of sync with the ReST docs.
-
-General Formatting
-------------------
-
-- Keep it 80-column clean. That means Emacs says the largest column
- number=79. If you haven't already, you should turn on column
- numbers to help you out:
-
- (column-number-mode 1)
-
- You can get more help from lineker-mode. Download it here:
-
- http://www.helsinki.fi/~sjpaavol/programs/lineker.el
-
- Then put the file somewhere in your load-path, and:
-
- (require 'lineker)
- (dolist (hook '(c-mode-hook c++-mode-hook))
- (add-hook hook (lambda () (lineker-mode 1))))
-
- There are only a few exceptional situations. The most important one
- is when specifying a lookup table like PIN_MAP where it'd be ugly to
- split each entry over multiple lines.
diff --git a/notes/dma.txt b/notes/dma.txt
new file mode 100644
index 0000000..97b23a0
--- /dev/null
+++ b/notes/dma.txt
@@ -0,0 +1,99 @@
+DMA Notes
+=========
+
+Medium-density devices have one DMA controller, DMA1. High-density
+devices and up also have DMA2. DMA1 has 7 channels; DMA2 has 5. Each
+channel multiplexes DMA requests from various peripherals, like so:
+
+Channel Capabilities
+--------------------
+
+DMA1:
+
+ * Channel 1: ADC1, TIM2_CH3, TIM4_CH1
+ * Channel 2: USART3_TX, TIM1_CH1, TIM2_UP, TIM3_CH3, SPI1_RX
+ * Channel 3: USART3_RX, TIM1_CH2, TIM3_CH4, TIM3_UP, SPI1_TX
+ * Channel 4: USART1_TX, TIM1_CH4, TIM1_TRIG, TIM1_COM, TIM4_CH2,
+ SPI2/I2S2_RX, I2C2_TX
+ * Channel 5: USART1_RX, TIM1_UP, TIM2_CH1, TIM4_CH3,
+ SPI2/I2S2_TX, I2C2_RX
+ * Channel 6: USART2_RX, TIM1_CH3, TIM3_CH1, TIM3_TRIG, I2C1_TX
+ * Channel 7: USART2_TX, TIM2_CH2, TIM2_CH4, TIM4_UP, I2C1_RX
+
+DMA2:
+
+ * Channel 1: TIM5_CH4, TIM5_TRIG, TIM8_CH3, TIM8_UP, SPI/I2S3_RX
+ * Channel 2: TIM8_CH4, TIM8_TRIG, TIM8_COM, TIM5_CH3, TIM5_UP, SPI/I2S3_TX
+ * Channel 3: TIM8_CH1, UART4_RX, TIM6_UP/DAC_CH1
+ * Channel 4: TIM5_CH2, SDIO, TIM7_UP/DAC_CH2
+ * Channel 5: ADC3, TIM8_CH2, TIM5_CH1, UART4_TX
+
+An example usage: via DMA1, channel 1, you can have ADC1 periodically
+dump converted data into an array in memory. The DMA controller can
+then interrupt you when the array is half-full and full, and if any
+error occurred.
+
+Since channels are multiplexed in hardware, you can't simultaneously
+use the same DMA channel to serve requests from two of its peripherals
+at the same time. For example, if you are using DMA 1 channel 1 to
+serve DMA requests from ADC1, you can't also serve requests from Timer
+2 channel 3.
+
+Channel Priority
+----------------
+
+An arbiter prioritizes simultaneous channel DMA requests. Channel
+priority levels are configurable (4 levels of priority). Ties within
+a DMA controller are broken by choosing the lower channel number;
+between the controllers, DMA1 has higher priority than DMA2.
+
+Interrupts
+----------
+
+You can cause an interrupt to fire once half the transfers are
+complete, when all the transfers are complete, if an error occurs
+during transfer, or any combination of the three.
+
+If an error occurs, the transfer is automatically disabled.
+
+Configuration
+-------------
+
+In order to configure a DMA transfer for DMA controller n, channel x,
+ST RM0008 says you should do the following:
+
+ A. Set the peripheral register address in DMAn_BASE->CPARx.
+ B. Set the memory address in DMAn_BASE->CMARx.
+ C. Set the number of data to be transferred in DMAn_BASE->CNDTRx.
+ D. Set the channel priority via the PL bits in DMAn_BASE->CCRx.
+ E. Configure various other things (e.g. data transfer sizes, what
+ events cause channel interrupts) in DMAn_BASE->CCRx as desired.
+ F. Activate the channel by setting ENABLE bit in DMAn_BASE->CCRx.
+
+The channel will start serving DMA requests as soon as it's activated.
+
+The DMA library lets you accomplish these tasks as follows:
+
+ **Setup transfer**
+
+ Do (A), (B), and (E) using dma_setup_transfer().
+
+ This also does (D), but chooses the lowest priority by default.
+
+ **Perform any other desired configuration**
+
+ You can do (C) using dma_set_num_transfers().
+
+ You can do (D) using dma_set_priority().
+
+ You can attach interrupt handlers with dma_attach_interrupt().
+
+ **Activate the channel**
+
+ Do (F) with dma_enable().
+
+Once you're all done, you can dma_disable() the channel. If you
+dma_detach_interrupt() an interrupt handler, the channel interrupts
+will stop firing, but the transfer itself won't stop until it's done
+(which never happens if you set the DMA_CIRC_MODE flag when you called
+dma_setup_transfer()).
diff --git a/notes/exti.txt b/notes/exti.txt
new file mode 100644
index 0000000..1ad49ee
--- /dev/null
+++ b/notes/exti.txt
@@ -0,0 +1,67 @@
+External interrupt notes.
+
+To generate the interrupt, the interrupt line should be configured
+and enabled. This is done by programming the two trigger registers
+with the desired edge detection and by enabling the interrupt
+request by writing a '1' to the corresponding bit in the interrupt
+mask register. When the selected edge occurs on the external
+interrupt line, an interrupt request is generated. The pending bit
+corresponding to the interrupt line is also set. This request is
+reset by writing a '1' in the pending register.
+
+Hardware interrupt selection:
+
+To configure the 20 lines as interrupt sources, use the following
+procedure:
+
+1) Configure AFIO_EXTICR[y] to select the source input for EXTIx
+ external interrupt
+2) Configure the mask bits of the 20 interrupt lines (EXTI_IMR)
+3) Configure the trigger selection bits of the interrupt lines
+ (EXTI_RTSR and EXTI_FTSR)
+4) Configure the enable and mask bits that control the NVIC_IRQ
+ channel mapped to the External Interrupt Controller (EXTI) so
+ that an inerrupt coming from one of the 20 lines can be
+ correctly acknowledged.
+
+AFIO clock must be on.
+
+RM0008, page 107: "PD0, PD1 cannot be used for external
+interrupt/event generation on 36, 48, 64-bin packages."
+
+----------------------------------------------------------------------------
+Pin to EXTI Line Mappings:
+EXTI0 EXTI1 EXTI2 EXTI3 EXTI4
+--------------------------------------------------------------------------
+D2/PA0 D3/PA1 D1/PA2 D0/A6/PA3 D10/A10/PA4
+D26/EXT7/PB0 D27/EXT8/PB1 D16/A2/PC2 D17/A3/PC3 D18/A4/PC4
+D14/A0/PC0 D15/PC1 D25/EXT5/PD2
+
+EXTI5 EXTI6 EXTI7 EXTI8 EXTI9
+----------------------------------------------------------------------------
+D13/A13/PA5 D12/A12/PA6 D11/A11/PA7 D6/PA8 D7/PA9
+D4/PB5 D5/PB6 D9/PB7 D38/PB8 D23/EXT4/PB9
+D19/A5/PC5 D34/EXTI15/PC6 D35/EXT16/PC7 D36/PC8 D37/EXT18/PC9
+
+EXTI10 EXTI11 EXTI12 EXTI13 EXTI14
+----------------------------------------------------------------------------
+D8/PA10 D29/EXT10/PB11 D30/EXTI1/PB12 D31/EXTI12/PB13 D32/EXT13/PB14
+D28/PB10 D20/EXTI1/PC13 D21/EXT2/PC14
+D25/PC10
+
+EXTI15
+----------------------------------------------------------------------------
+D33/EXTI14/PB15
+D22/EXT3/PC15
+
+
+The 16 EXTI interrupts are mapped to 7 interrupt handlers.
+
+EXTI Lines to Interrupt Mapping:
+EXTI0 -> EXTI0
+EXTI1 -> EXTI1
+EXTI2 -> EXTI2
+EXTI3 -> EXTI3
+EXTI4 -> EXTI4
+EXTI[5-9] -> EXT9_5
+EXTI[10-15] -> EXT15_10
diff --git a/notes/native-pin-definitions.txt b/notes/pin-definitions.txt
index b871f89..30f5056 100644
--- a/notes/native-pin-definitions.txt
+++ b/notes/pin-definitions.txt
@@ -1,21 +1,18 @@
-Maple Native (STM32F103ZE) pin definitions, by GPIO bank.
+Pin definitions by GPIO bank.
Source: ST DOC ID 14611, Datasheet for STM32F103xC, STM32F103xD,
STM32F103xE, Table 5, pp. 30--35.
-Some peripherals and extra functionality with less/no libmaple
-relevance (at time of writing) are given in "Other" following each
-bank's main table. Non-default alternate functions are not listed. If
-wirish will/does remap the pin's main function after reset, the main
-function is listed under "Other".
+Some additional peripheral GPIO information is given in the "Other"
+section following each bank's main table.
-This document was prepared carefully and is believed to be complete
-and correct, but the final arbiter of truth is the ST datasheet.
+This document was prepared carefully and is believed to be correct,
+but the final arbiter of truth is the ST datasheet.
*** NB: UART 4 and 5 are NOT USART (columns are labeled appropriately).
---------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C USART SPI DAC 5v?
+GPIO ADC Timer FSMC I2S I2C USART SPI DAC 5v?
---------------------------------------------------------------------------
PA0 123in0 2ch1etr - - - 2cts - - -
5ch1
@@ -52,7 +49,7 @@ PA14: JTCK-SWCLK (default)
PA15: JTDI (default)
-------------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C USART SPI DAC 5v? SDIO
+GPIO ADC Timer FSMC I2S I2C USART SPI DAC 5v? SDIO
-------------------------------------------------------------------------------
PB0 12in8 3ch3 - - - - - - - -
8ch2n
@@ -80,7 +77,7 @@ PB3: JTDO (default)
PB4: NJTRST (default)
-------------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C UART SPI DAC 5v? SDIO
+GPIO ADC Timer FSMC I2S I2C UART SPI DAC 5v? SDIO
-------------------------------------------------------------------------------
PC0 123in10 - - - - - - - - -
PC1 123in11 - - - - - - - - -
@@ -106,7 +103,7 @@ PC14: OSC32_IN
PC15: OSC32_OUT
-------------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C UART SPI DAC 5v? SDIO
+GPIO ADC Timer FSMC I2S I2C UART SPI DAC 5v? SDIO
-------------------------------------------------------------------------------
PD0 - - D2 - - - - - Y -
PD1 - - D3 - - - - - Y -
@@ -132,7 +129,7 @@ PD0: OSC_IN (default)
PD1: OSC_OUT (default)
---------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C USART SPI DAC 5v?
+GPIO ADC Timer FSMC I2S I2C USART SPI DAC 5v?
---------------------------------------------------------------------------
PE0 - 4etr NBL0 - - - - - Y
PE1 - - NBL1 - - - - - Y
@@ -159,7 +156,7 @@ PE5: TRACED2
PE6: TRACED3
---------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C USART SPI DAC 5v?
+GPIO ADC Timer FSMC I2S I2C USART SPI DAC 5v?
---------------------------------------------------------------------------
PF0 - - A0 - - - - - Y
PF1 - - A1 - - - - - Y
@@ -179,7 +176,7 @@ PF14 - - A8 - - - - - Y
PF15 - - A9 - - - - - Y
---------------------------------------------------------------------------
-STM32 ADC Timer FSMC I2S I2C USART SPI DAC 5v?
+GPIO ADC Timer FSMC I2S I2C USART SPI DAC 5v?
---------------------------------------------------------------------------
PG0 - - A10 - - - - - Y
PG1 - - A11 - - - - - Y
diff --git a/notes/portable.txt b/notes/portable.txt
index 69952d7..cc1f2ac 100644
--- a/notes/portable.txt
+++ b/notes/portable.txt
@@ -1,98 +1,28 @@
+Board portability is implemented in boards.h, libmaple.h, and stm32.h.
-Disclaimer text: // High-density devices only (Maple Native)
+At compile time, we currently expect one of STM32_MEDIUM_DENSITY or
+STM32_HIGH_DENSITY to be defined. There's no support for low-density
+chips. XL-density isn't in the near horizon; patches welcome. You'll
+also need to define some BOARD_foo if you expect to use Wirish; this
+comes along with some additional assumptions about your board's layout.
+The code in usb/ is not very portable at all right now; expect this to
+change in the future, but for now, we're focusing on rolling out a
+more complete backend.
-Board portability is implemented by adding a header file to ./libmaple with the
-name of the BOARD target, and then editing libmaple.h to add this file as an
-option.
-
-A pin maple file should be added to ./notes describing the pin numbering
-
-Files to check by hand:
-# adc.c
-# adc.h
-# exc.c
-# exti.c
-# exti.h
-# flash.c
-# flash.h
-# gpio.c
-# gpio.h
-# libmaple_types.h
-# nvic.c
-# nvic.h
-# rcc.c
-# rcc.h
-# ring_buffer.h
-# rules.mk
-# spi.c
-- spi.h
-# syscalls.c
-# systick.c
-# systick.h
-# timers.c
-# timers.h
-# usart.c
-# usart.h
-# util.c
-# util.h
-# libmaple.h
-# usb/*
-
-wirish/:
-# bits.h
-# boards.h
-# cxxabi-compat.cpp
-# ext_interrupts.c
-# ext_interrupts.h
-# HardwareTimer.cpp
-# HardwareTimer.h
-# io.h
-# main.cxx
-# Print.cpp
-# Print.h
-# pwm.c
-# pwm.h
-# rules.mk
-# time.c
-# time.h
-# usb_serial.cpp
-# usb_serial.h
-# wirish_analog.c
-# wirish.c
-# wirish_digital.c
-# wirish.h
-# wirish_math.cpp
-# wirish_math.h
-# wirish_shift.c
-# WProgram.h
-- comm/
-
-
-
-ADC Notes:
- only using ADC1?
- untested
-
-EXTI Notes:
- need to update huge table in comments?
- untested
+A file should be added to ./notes describing the pin numbering of any
+new board you add.
NVIC Notes:
- I don't think NVIC_ISER3 and NVIC_ICER3 actually exist?
Only CANBUS and USB OTG use interrupts above #63, but I updated the nvic code anyways
RCC Notes:
Added some clock stuff to all boards even though they aren't usable... blah.
SPI Notes:
- SPI3 is only in XL chips so didn't really handle that
+ SPI3 is only in XL chips, so we don't handle that.
TIMER Notes:
- High-density devices add an advanced timer (TIMER8) and another normal one (TIMER5).
- TIMER6 and TIMER7 are much less useful.
- There is some partial progress towards adding timer5/timer8 functionality,
- but not much. This should probably all be rewritten.
The wirish timer implementation should be refactored to use pin numbers.
USART Notes:
diff --git a/notes/timers.txt b/notes/timers.txt
index 3f5b9f4..647e92e 100644
--- a/notes/timers.txt
+++ b/notes/timers.txt
@@ -1,82 +1,87 @@
+Timers
+======
-Each timer (1-4) has 4 capture/compare channels (1-4). These are directly used
-by PWM but have a ton of other possible functionality. The STM32 implementation
-is particularly complicated with, eg, the ability to chain together timers
-
-Timer1 is an "advanced timer" with many more features. I think if we use just
-the "Capture and compare interrupt", and enable MOE during initialization
-everything will be ok. There are seperate Break, Update, and Trigger interrupts
-as well that we will ignore for now.
-
-Timer2,Ch 3+4 are D0 and D1, which conflict with Serial2. USART should work
-fine as long as pins aren't in output mode? and timers should work fine if
-Serial2 isn't in use?
-
-Caveats
-------------------------------------------------------------------------------
-There are probably subtle bugs with the way register settings get read in; eg,
-it is often required to have the counter fully overflow before new settings
-come into effect?
-Getting really good timing is still an art, not a science here... usually you
-need to fiddle with an oscilloscope and the exact overflow/compare numbers to
-get just the right time values.
-Any other interrupts (SysTick, USB, Serial, etc) can blow away all the nice
-timing stuff.
-
-Misc Notes
-------------------------------------------------------------------------------
-Implementation with case/switch in the interrupt handlers doesn't work; a lot
-of the time multiple interrupt flags are active at the same time (or become
-active?)
+Medium-density chips have timers 1 through 4. High- and XL-density
+chips additionally have timers 5 through 8. XL-density chips
+additionally have timers 9--14, which we don't support yet.
+
+Timer Capabilities
+------------------
+
+Each of timers 1--4 has 4 capture/compare (C/C) channels (also numbered
+1--4). These are directly used by PWM, but may serve other purposes as
+well (including handling user-specified periodic interrupts). The
+STM32 implementation is particularly featureful, with, e.g., the
+ability to chain together timers.
+
+Timers 1 and 8 are an advanced timers, with many more features.
+Wirish just uses just their capture/compare interrupts and enables MOE
+during initialization, essentially treating them as general purpose
+timers (like timers 2--5). Advanced timers also have separate break,
+update, and trigger interrupts that we only provide low-level
+(i.e. libmaple proper) support for.
+
+Timers 6 and 7 are basic timers, without C/C channels. They are still
+useful for interrupts (via NVIC_TIMER6, NVIC_TIMER7 IRQs, which can
+fire upon an update event), but they're most useful for controlling
+periodic DAC output.
+
+Known Issues and Other Caveats
+------------------------------
+
+There are some conflicts between timer C/C outputs and USART 1 and 2
+TX/RX. Wirish tries to handle this gracefully, but (as of 7 April
+2011) not all the bugs are sorted yet. In particular, if you call
+HardwareSerial::disable(), then try to use PWM, the USART TX pins
+don't cooperate.
+
+Resetting the prescaler or reload value only takes effect at the next
+update event. You can use timer_generate_update() to generate an
+update event via software.
+
+Other interrupts (SysTick, USB, Serial, etc.) can interfere with
+timing-critical applications. If your program requires precise
+timing, you should probably at least disable USB and SysTick. Note
+that this also disables the bootloader and stops millis()/micros()
+from counting.
+
+Getting really good timing is a bit of an art. If things don't work
+at first, you need to fiddle with an oscilloscope and the exact
+overflow/compare numbers to get precise behavior.
TODO
-------------------------------------------------------------------------------
-- document carefully (eg, determine clock-wise and overflow-wise behavior for
- each function)
-- track down and handle all pin conflicts
-- implement the update interrupt as a "5th channel"
-- "pulse in" stuff, both c and c++
-- function to read out CCR registers
-- allow comparison output to the pin (a la PWM)
-- additional modes and configuration (up, down, up/down, etc)
-
-Possible Wirish implementation
-------------------------------------------------------------------------------
-Inspired by Timer1 Library for arduino
-http://arduino.cc/pipermail/developers_arduino.cc/2010-June/002845.html
+----
+
+- Document more carefully (e.g., determine clock-wise and
+ overflow-wise behavior for each function).
- class HardwareTimer {
-
- public:
-
- void pause();
- void resume();
- void setPrescaleFactor(uint8 factor);
- void setOverflow(uint16 val); // truncates to overflow
- void setCount(uint16 val); // truncates to overflow
- uint16 getCount();
- uint16 setPeriod(uint32 microseconds); // tries to set prescaler and overflow wisely; returns overflow
- void setMode(uint8 mode);
- void setCompare1(uint16 val); // truncates to overflow
- void setCompare2(uint16 val); // truncates to overflow
- void setCompare3(uint16 val); // truncates to overflow
- void setCompare4(uint16 val); // truncates to overflow
- void attachCompare1Interrupt(void (*f)(void));
- void attachCompare2Interrupt(void (*f)(void));
- void attachCompare3Interrupt(void (*f)(void));
- void attachCompare4Interrupt(void (*f)(void));
- void detachCompare1Interrupt();
- void detachCompare2Interrupt();
- void detachCompare3Interrupt();
- void detachCompare4Interrupt();
- };
-
- HardwareTimer Timer1 = HardwareTimer(1);
- HardwareTimer Timer2 = HardwareTimer(2);
- HardwareTimer Timer3 = HardwareTimer(3);
- HardwareTimer Timer4 = HardwareTimer(4);
+- Track down and handle pin conflicts.
+
+- Input capture interface. DON'T WRITE pulseIn() IN TERMS OF THIS.
+ Do that as a simple, Arduino style implementation that just
+ busy-waits and uses micros(), to allow a pulseIn() on arbitrary
+ pins. Eventually, expose the more precise/harder to use timer-based
+ API via a convenience library.
+
+- Complementary outputs, with convenient break/dead time interface.
+
+- Additional modes (center-aligned PWM, one pulse mode, etc.) and
+ count configuration (down, up/down).
+
+Alternative Wirish Implementations
+----------------------------------
+
+The current Wirish API is big and clunky. Its inclusion by default
+also threatens making everyone's sketches bigger unnecessarily. We
+need to deprecate the parts of it that are bad for 0.0.10, and remove
+them when 0.1.0 comes out.
+
+Current implementation was inspired by Timer1 Library for Arduino:
+
+http://arduino.cc/pipermail/developers_arduino.cc/2010-June/002845.html
Here's one of the more standard libaries out there:
+
http://www.arduino.cc/playground/Code/Timer1
void initialize(long microseconds=1000000);
@@ -89,4 +94,3 @@ http://www.arduino.cc/playground/Code/Timer1
void disablePwm(char pin);
void attachInterrupt(void (*isr)(), long microseconds=-1);
void detachInterrupt();
-
diff --git a/notes/usb.txt b/notes/usb.txt
index 5e00354..9552b9f 100644
--- a/notes/usb.txt
+++ b/notes/usb.txt
@@ -1,3 +1,7 @@
+XXX
+XXX This file may be out of date!
+XXX
+
[NOTE: this is a long term proposal. The current implementation just does a
2ms TIMEOUT]
diff --git a/notes/vga.txt b/notes/vga.txt
index d75281a..43b6830 100644
--- a/notes/vga.txt
+++ b/notes/vga.txt
@@ -7,8 +7,7 @@ gpio_write_bit() is about 360ns (2.78MHz)
Writing to GPIO?_BASE is about 60ns (16.6MHz -> 18MHz)
-pwm write 0x0001 is about 30ns (33MHz) with prescaler as 1 (default)
-pwm write 0x0001 is about 14ns (72MHz) with prescaler as 0 (!)
+PWM write 0x0001 is about 14ns (72MHz) with prescaler as 0 (!)
VGA Timing
------------------------------------------------------------------------------
@@ -34,9 +33,3 @@ Crude 640x480 directions:
11 lines front porch
2 lines Vsync (low)
31 lines back porch
-
-Currently, setting vs. clearing GPIO registers seems to take a different amount
-of time? Or perhaps i'm not analyzing branching correctly. Regardless, if you
-SET 100x times then UNSET on one line, then UNSET 100x then SET the next line,
-the two changes in color will generally not line up.
-