diff options
author | Marti Bolivar <mbolivar@leaflabs.com> | 2011-05-09 16:43:27 -0400 |
---|---|---|
committer | Marti Bolivar <mbolivar@leaflabs.com> | 2011-05-09 16:49:08 -0400 |
commit | 19ea6ba4ea3f1ecb9830cf4d3e1366513f4f96e3 (patch) | |
tree | a43f7e0fb3650ca54f245b750a078a0e8c356504 /notes | |
parent | 868fb1c273e562a1140abfa948022c9d4f55bccf (diff) | |
parent | 1e2e177f6dae62e040c674b617744c73be187062 (diff) | |
download | librambutan-19ea6ba4ea3f1ecb9830cf4d3e1366513f4f96e3.tar.gz librambutan-19ea6ba4ea3f1ecb9830cf4d3e1366513f4f96e3.zip |
Merge branch 'refactor'
This merges the libmaple refactor work into master. The contents of
libmaple proper (/libmaple/) are almost completely incompatible with
previous APIs in master. See /docs/source/libmaple/overview.rst for
more information on the new design.
Wirish incompatibilities are limited to the HardwareTimer class;
however, there are several new deprecations, most likely to be removed
in 0.1.0.
Diffstat (limited to 'notes')
-rw-r--r-- | notes/coding_standard.rst | 427 | ||||
-rw-r--r-- | notes/coding_standard.txt | 223 | ||||
-rw-r--r-- | notes/dma.txt | 99 | ||||
-rw-r--r-- | notes/exti.txt | 67 | ||||
-rw-r--r-- | notes/pin-definitions.txt (renamed from notes/native-pin-definitions.txt) | 27 | ||||
-rw-r--r-- | notes/portable.txt | 94 | ||||
-rw-r--r-- | notes/timers.txt | 152 | ||||
-rw-r--r-- | notes/usb.txt | 4 | ||||
-rw-r--r-- | notes/vga.txt | 9 |
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. - |