diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/blinky.cpp | 2 | ||||
-rw-r--r-- | examples/debug-dtrrts.cpp | 12 | ||||
-rw-r--r-- | examples/freertos-blinky.cpp | 2 | ||||
-rw-r--r-- | examples/fsmc-stress-test.cpp | 6 | ||||
-rw-r--r-- | examples/i2c-mcp4725-dac.cpp | 145 | ||||
-rw-r--r-- | examples/mini-exti-test.cpp | 2 | ||||
-rw-r--r-- | examples/qa-slave-shield.cpp | 2 | ||||
-rw-r--r-- | examples/serial-echo.cpp | 30 | ||||
-rw-r--r-- | examples/spi_master.cpp | 2 | ||||
-rw-r--r-- | examples/test-bkp.cpp | 6 | ||||
-rw-r--r-- | examples/test-dac.cpp | 4 | ||||
-rw-r--r-- | examples/test-fsmc.cpp | 4 | ||||
-rw-r--r-- | examples/test-print.cpp | 2 | ||||
-rw-r--r-- | examples/test-ring-buffer-insertion.cpp | 4 | ||||
-rw-r--r-- | examples/test-serial-flush.cpp | 2 | ||||
-rw-r--r-- | examples/test-serialusb.cpp | 6 | ||||
-rw-r--r-- | examples/test-servo.cpp | 2 | ||||
-rw-r--r-- | examples/test-session.cpp | 2 | ||||
-rw-r--r-- | examples/test-spi-roundtrip.cpp | 2 | ||||
-rw-r--r-- | examples/test-systick.cpp | 4 | ||||
-rw-r--r-- | examples/test-timers.cpp | 710 | ||||
-rw-r--r-- | examples/test-usart-dma.cpp | 220 | ||||
-rw-r--r-- | examples/vga-leaf.cpp | 2 | ||||
-rw-r--r-- | examples/vga-scope.cpp | 4 |
24 files changed, 839 insertions, 338 deletions
diff --git a/examples/blinky.cpp b/examples/blinky.cpp index dd72514..fad71f8 100644 --- a/examples/blinky.cpp +++ b/examples/blinky.cpp @@ -1,6 +1,6 @@ // Blinks the built-in LED -#include "wirish.h" +#include <wirish/wirish.h> void setup() { pinMode(BOARD_LED_PIN, OUTPUT); diff --git a/examples/debug-dtrrts.cpp b/examples/debug-dtrrts.cpp index 3829208..75eceef 100644 --- a/examples/debug-dtrrts.cpp +++ b/examples/debug-dtrrts.cpp @@ -1,7 +1,7 @@ // Test sketch for figuring out DTR/RTS behavior on different platforms. -#include "wirish.h" -#include "usb.h" +#include <wirish/wirish.h> +#include "usb_cdcacm.h" void setup() { /* Set up the LED to blink */ @@ -10,7 +10,6 @@ void setup() { /* Send a message out USART2 */ Serial2.begin(9600); Serial2.println("Debugging DTR/RTS..."); - } void loop() { @@ -18,9 +17,9 @@ void loop() { delay(100); Serial2.print("DTR: "); - Serial2.print(usbGetDTR(), DEC); + Serial2.print(usb_cdcacm_get_dtr(), DEC); Serial2.print("\tRTS: "); - Serial2.println(usbGetRTS(), DEC); + Serial2.println(usb_cdcacm_get_rts(), DEC); } // Force init to be called *first*, i.e. before static object allocation. @@ -32,9 +31,8 @@ __attribute__((constructor)) void premain() { int main(void) { setup(); - while (1) { + while (true) { loop(); } return 0; } - diff --git a/examples/freertos-blinky.cpp b/examples/freertos-blinky.cpp index 6f82d71..2e7c7f7 100644 --- a/examples/freertos-blinky.cpp +++ b/examples/freertos-blinky.cpp @@ -1,4 +1,4 @@ -#include "wirish.h" +#include <wirish/wirish.h> #include "libraries/FreeRTOS/MapleFreeRTOS.h" static void vLEDFlashTask(void *pvParameters) { diff --git a/examples/fsmc-stress-test.cpp b/examples/fsmc-stress-test.cpp index 509a02f..20d3fa7 100644 --- a/examples/fsmc-stress-test.cpp +++ b/examples/fsmc-stress-test.cpp @@ -12,9 +12,9 @@ #include <stdio.h> #include <stddef.h> -#include "wirish.h" -#include "rcc.h" -#include "fsmc.h" +#include <wirish/wirish.h> +#include <libmaple/rcc.h> +#include <libmaple/fsmc.h> // -- SRAM config ------------------------------------------------------------- diff --git a/examples/i2c-mcp4725-dac.cpp b/examples/i2c-mcp4725-dac.cpp new file mode 100644 index 0000000..da9a34e --- /dev/null +++ b/examples/i2c-mcp4725-dac.cpp @@ -0,0 +1,145 @@ +// i2c-mcp4725-dac.cpp +// +// Written by Andrew Meyer <ajm@leaflabs.com> +// Modified by Marti Bolivar <mbolivar@leaflabs.com> +// +// Simple program showing how to control an MCP4725 DAC using the +// libmaple I2C interface. There's an MCP4725 breakout board available +// on SparkFun: +// +// http://www.sparkfun.com/products/8736 +// +// How to use: +// +// 1. Connect the DAC SDA and SCL pins to I2C2, with a pullup +// resistor (1 KOhm should work) to VCC. +// 2. Load the sketch and connect to SerialUSB. +// 3. Press the button. +// +// The program then makes sure the DAC is connected properly (during +// setup()), then has the DAC output a sawtooth wave (with loop()). + +#include <wirish/wirish.h> +#include <libmaple/i2c.h> + +#define MCP_ADDR 0x60 +#define MCP_WRITE_DAC 0b01000000 +#define MCP_WRITE_EEPROM 0b01100000 +#define MCP_PD_NORMAL 0b00000000 +#define MCP_PD_1K 0b00000010 +#define MCP_PD_100K 0b00000100 +#define MCP_PD_500K 0b00000110 + +static uint8 write_msg_data[3]; +static i2c_msg write_msg; + +static uint8 read_msg_data[5]; +static i2c_msg read_msg; + +/* + * DAC control routines + */ + +void mcp_i2c_setup(void) { + write_msg.addr = MCP_ADDR; + write_msg.flags = 0; // write, 7 bit address + write_msg.length = sizeof(write_msg_data); + write_msg.xferred = 0; + write_msg.data = write_msg_data; + + read_msg.addr = MCP_ADDR; + read_msg.flags = I2C_MSG_READ; + read_msg.length = sizeof(read_msg_data); + read_msg.xferred = 0; + read_msg.data = read_msg_data; +} + +void mcp_write_val(uint16 val) { + write_msg_data[0] = MCP_WRITE_DAC | MCP_PD_NORMAL; + uint16 tmp = val >> 4; + write_msg_data[1] = tmp; + tmp = (val << 4) & 0x00FF; + write_msg_data[2] = tmp; + + i2c_master_xfer(I2C2, &write_msg, 1, 0); +} + +uint16 mcp_read_val() { + uint16 tmp = 0; + + i2c_master_xfer(I2C2, &read_msg, 1, 2); + + /* We don't care about the status and EEPROM bytes (0, 3, and 4). */ + tmp = (read_msg_data[1] << 4); + tmp += (read_msg_data[2] >> 4); + return tmp; +} + +int mcp_test() { + uint16 val; + uint16 test_val = 0x0101; + + SerialUSB.println("Testing the MCP4725..."); + /* Read the value of the register (should be 0x0800 if factory fresh) */ + val = mcp_read_val(); + SerialUSB.print("DAC Register = 0x"); + SerialUSB.println(val, HEX); + + mcp_write_val(test_val); + SerialUSB.print("Wrote 0x"); + SerialUSB.print(test_val, HEX); + SerialUSB.println(" to the DAC"); + + val = mcp_read_val(); + SerialUSB.print("DAC Register = 0x"); + SerialUSB.println(val, HEX); + + if (val != test_val) { + SerialUSB.println("ERROR: MCP4725 not responding correctly"); + return 0; + } + + SerialUSB.println("MCP4725 seems to be working"); + return 1; +} + +/* + * setup() and loop() + */ + +void setup() { + pinMode(BOARD_BUTTON_PIN, INPUT); + i2c_master_enable(I2C2, 0); + mcp_i2c_setup(); + + waitForButtonPress(); + ASSERT(mcp_test()); + + SerialUSB.println("Starting sawtooth wave"); +} + +void loop() { + static uint16 dout = 0; + + mcp_write_val(dout); + + dout += 50; + if (dout >= 32768) { + dout = 0; + } +} + +// -- init() and main() ------------------------------------------------------- + +__attribute__((constructor)) void premain() { + init(); +} + +int main(void) { + setup(); + + while (true) { + loop(); + } + return 0; +} diff --git a/examples/mini-exti-test.cpp b/examples/mini-exti-test.cpp index 84b323e..54a4dd0 100644 --- a/examples/mini-exti-test.cpp +++ b/examples/mini-exti-test.cpp @@ -10,7 +10,7 @@ #include <stdio.h> #include <string.h> -#include "wirish.h" +#include <wirish/wirish.h> // test routines void run_exti_test(void); diff --git a/examples/qa-slave-shield.cpp b/examples/qa-slave-shield.cpp index 2da1c04..ec25e49 100644 --- a/examples/qa-slave-shield.cpp +++ b/examples/qa-slave-shield.cpp @@ -1,6 +1,6 @@ // Slave mode for Quality Assurance test -#include "wirish.h" +#include <wirish/wirish.h> #define INTER_TOGGLE_DELAY_NORMAL 5 #define INTER_TOGGLE_DELAY_SLOW 80 diff --git a/examples/serial-echo.cpp b/examples/serial-echo.cpp new file mode 100644 index 0000000..204f011 --- /dev/null +++ b/examples/serial-echo.cpp @@ -0,0 +1,30 @@ +// Simple serial port "echo". Send back any received data. + +#include <wirish/wirish.h> + +// Note: you can change "Serial1" to any other serial port you have on +// your board. + +void setup() { + Serial1.begin(115200); +} + +void loop() { + while (Serial1.available()) { + Serial1.write(Serial1.read()); + } +} + +// Force init() to be called before anything else. +__attribute__((constructor)) void premain() { + init(); +} + +int main(void) { + setup(); + + while (true) { + loop(); + } + return 0; +} diff --git a/examples/spi_master.cpp b/examples/spi_master.cpp index 100fc53..ea6c990 100644 --- a/examples/spi_master.cpp +++ b/examples/spi_master.cpp @@ -33,7 +33,7 @@ * Pin 10 is used as slave select. */ -#include "wirish.h" +#include <wirish/wirish.h> #define NSS 10 diff --git a/examples/test-bkp.cpp b/examples/test-bkp.cpp index f5957b7..719cac7 100644 --- a/examples/test-bkp.cpp +++ b/examples/test-bkp.cpp @@ -1,8 +1,8 @@ #include <stdio.h> // for snprintf() -#include "wirish.h" -#include "bkp.h" -#include "iwdg.h" +#include <wirish/wirish.h> +#include <libmaple/bkp.h> +#include <libmaple/iwdg.h> void print_bkp_contents(); void write_to_bkp(uint16 val); diff --git a/examples/test-dac.cpp b/examples/test-dac.cpp index 40ae5d5..af188cc 100644 --- a/examples/test-dac.cpp +++ b/examples/test-dac.cpp @@ -6,8 +6,8 @@ * This file is released into the public domain. */ -#include "wirish.h" -#include "dac.h" +#include <wirish/wirish.h> +#include <libmaple/dac.h> uint16 count = 0; diff --git a/examples/test-fsmc.cpp b/examples/test-fsmc.cpp index 22f6975..1621317 100644 --- a/examples/test-fsmc.cpp +++ b/examples/test-fsmc.cpp @@ -1,7 +1,7 @@ #include <stddef.h> // for ptrdiff_t -#include "wirish.h" -#include "fsmc.h" +#include <wirish/wirish.h> +#include <libmaple/fsmc.h> #ifndef BOARD_maple_native #error "Sorry, this example only works on Maple Native." diff --git a/examples/test-print.cpp b/examples/test-print.cpp index 5477512..bdc1894 100644 --- a/examples/test-print.cpp +++ b/examples/test-print.cpp @@ -8,7 +8,7 @@ * This file is released into the public domain. */ -#include "wirish.h" +#include <wirish/wirish.h> #undef min #undef max diff --git a/examples/test-ring-buffer-insertion.cpp b/examples/test-ring-buffer-insertion.cpp index e86372a..2188b03 100644 --- a/examples/test-ring-buffer-insertion.cpp +++ b/examples/test-ring-buffer-insertion.cpp @@ -12,9 +12,9 @@ * This file is released into the public domain. */ -#include "wirish.h" +#include <wirish/wirish.h> -#include "ring_buffer.h" +#include <libmaple/ring_buffer.h> #define BUF_SIZE 64 ring_buffer ring_buf; diff --git a/examples/test-serial-flush.cpp b/examples/test-serial-flush.cpp index adc9c3e..409d1f9 100644 --- a/examples/test-serial-flush.cpp +++ b/examples/test-serial-flush.cpp @@ -2,7 +2,7 @@ * Tests the "flush" Serial function. */ -#include "wirish.h" +#include <wirish/wirish.h> void setup() { Serial1.begin(9600); diff --git a/examples/test-serialusb.cpp b/examples/test-serialusb.cpp index 15ab913..098e445 100644 --- a/examples/test-serialusb.cpp +++ b/examples/test-serialusb.cpp @@ -1,7 +1,7 @@ // Tests SerialUSB functionality. -#include "wirish.h" -#include "usb.h" +#include <wirish/wirish.h> +#include "usb_cdcacm.h" #define QUICKPRINT 0 #define BIGSTUFF 1 @@ -37,7 +37,7 @@ void loop() { switch (state) { case QUICKPRINT: for (int i = 0; i < 30; i++) { - usbSendBytes(&c1, 1); + usb_cdcacm_putc((char)c1, 1); SerialUSB.print('.'); SerialUSB.print('|'); } diff --git a/examples/test-servo.cpp b/examples/test-servo.cpp index b6b8cd5..6f6e3ba 100644 --- a/examples/test-servo.cpp +++ b/examples/test-servo.cpp @@ -29,7 +29,7 @@ #include <stdio.h> -#include "wirish.h" +#include <wirish/wirish.h> #include "libraries/Servo/Servo.h" diff --git a/examples/test-session.cpp b/examples/test-session.cpp index 6c7cfff..4316cda 100644 --- a/examples/test-session.cpp +++ b/examples/test-session.cpp @@ -4,7 +4,7 @@ // Useful for testing Maple features and troubleshooting. // Communicates over SerialUSB. -#include "wirish.h" +#include <wirish/wirish.h> // ASCII escape character #define ESC ((uint8)27) diff --git a/examples/test-spi-roundtrip.cpp b/examples/test-spi-roundtrip.cpp index 71ae658..ddc9875 100644 --- a/examples/test-spi-roundtrip.cpp +++ b/examples/test-spi-roundtrip.cpp @@ -17,7 +17,7 @@ * Author: Marti Bolivar <mbolivar@leaflabs.com> */ -#include "wirish.h" +#include <wirish/wirish.h> HardwareSPI alice(2); diff --git a/examples/test-systick.cpp b/examples/test-systick.cpp index 78c7307..356f302 100644 --- a/examples/test-systick.cpp +++ b/examples/test-systick.cpp @@ -1,7 +1,7 @@ // Tests the SysTick enable/disable functions -#include "wirish.h" -#include "systick.h" +#include <wirish/wirish.h> +#include <libmaple/systick.h> void setup() { pinMode(BOARD_LED_PIN, OUTPUT); diff --git a/examples/test-timers.cpp b/examples/test-timers.cpp index 247cc57..e646916 100644 --- a/examples/test-timers.cpp +++ b/examples/test-timers.cpp @@ -1,288 +1,528 @@ -// Program to test the timer.h implementation's essential functionality. - -#include "wirish.h" -#include "timer.h" - -void handler1(void); -void handler2(void); -void handler3(void); -void handler4(void); - -void handler3b(void); -void handler4b(void); - -int t; - -int count1 = 0; -int count2 = 0; -int count3 = 0; -int count4 = 0; -uint16 rate1 = 1000; -uint16 rate2 = 2000; -uint16 rate3 = 4000; -uint16 rate4 = 8000; -uint16 val1 = 10000; -uint16 val2 = 10000; -uint16 val3 = 10000; -uint16 val4 = 10000; - -// FIXME [0.1.0] high density timer test (especially basic timers + DAC) -timer_dev *timers[] = {TIMER1, TIMER2, TIMER3, TIMER4}; -voidFuncPtr handlers[] = {handler1, handler2, handler3, handler4}; - -void initTimer(timer_dev *dev); -void setTimerPeriod(timer_dev *dev, uint32 period_us); -void testSetTimerPeriod(uint32 period); -void testTimerChannels(timer_dev *dev); -int timerNumber(timer_dev *dev); +// +// This is a mostly Wirish-free timer test. Wirish usage is minimized +// because this is a test of the C timer interface in +// <libmaple/timer.h>, so it's good if it can be made to work even +// when most or all of Wirish is missing. Because of that, you may +// need to customize the following output configuration: +// +// Output is printed: +// - on COMM_USART, +// - via TX pin on port COMM_USART_PORT, bit COMM_USART_TX_BIT +// - via RX pin on port COMM_USART_PORT, bit COMM_USART_RX_BIT +// - at COMM_USART_BAUD baud. +#define COMM_USART USART6 +#define COMM_USART_BAUD 115200 +#define COMM_USART_PORT GPIOG +#define COMM_USART_TX_BIT 14 +#define COMM_USART_RX_BIT 9 +// Other optional configuration below. + +#include <libmaple/libmaple.h> +#include <libmaple/gpio.h> +#include <libmaple/usart.h> +#include <libmaple/systick.h> +#include <libmaple/timer.h> +#include <wirish/boards.h> + +// +// Configuration +// + +// More output if true +static bool verbose = true; + +// Timers to test +// FIXME use feature test macros for smaller MCUs +static timer_dev *timers[] = { + // Available on all currently supported MCUs + TIMER1, TIMER2, TIMER3, TIMER4, + // Available on F1 (HD and up), F2 + TIMER5, TIMER6, TIMER7, TIMER8, + // Available on F1 (XL), F2 + TIMER9, TIMER10, TIMER11, TIMER12, TIMER13, TIMER14, +}; + +// +// Test routines +// + +typedef void (*timer_test_t)(timer_dev *); + +static void runTest(const char description[], timer_test_t test); +static void runTests(void); + +static void testGetAndSetCount(timer_dev*); +static void testPauseAndResume(timer_dev*); +static void testTimerChannels(timer_dev*); + +// +// Helpers +// + +static void initTimer(timer_dev *dev); +static int timerNumber(timer_dev *dev); +// Hack: a systick-based delay, useful until delay_us() is fixed +static void _delay(uint32 msec); +// Wirish-less USART initialization routine +static void init_usart(usart_dev *dev, gpio_dev *gdev, uint8 tx, uint8 rx); +// Return whether or not the timer has capture/compare channel `ch'. +// TODO: does something like this belong in the standard timer library? +static bool timer_has_cc_ch(timer_dev *dev, int ch); + +// Printing routines and variants for verbose mode +static void putstr(const char str[]); +static void println(void); +static void putstrln(const char str[]); +static void putudec(uint32 val); +static void puttimn(timer_dev *dev); +static void v_putstr(const char str[]); +static void v_println(); +static void v_putstrln(const char str[]); +static void v_putudec(uint32 val); +static void v_puttimn(timer_dev *dev); +// Used to visually separate output from different tests +static void printBanner(void); + +// +// Handler state +// + +static int count1 = 0; +static int count2 = 0; +static int count3 = 0; +static int count4 = 0; +static int timer_num; // Current timer we're considering + +// +// Timer capture/compare interrupt handlers +// +// These are shared between timers. The global variable timer_num +// controls which timer they affect. +// + +static void handler1(void); +static void handler2(void); +static void handler3(void); +static void handler4(void); +static voidFuncPtr handlers[] = {handler1, handler2, handler3, handler4}; + +// +// setup() and loop() +// void setup() { - // Set up the LED to blink - pinMode(BOARD_LED_PIN, OUTPUT); - - // Setup the button as input - pinMode(BOARD_BUTTON_PIN, INPUT); - - // Send a message out Serial2 - Serial2.begin(115200); - Serial2.println("*** Initializing timers..."); + init_usart(COMM_USART, COMM_USART_PORT, + COMM_USART_TX_BIT, COMM_USART_RX_BIT); + _delay(5); + println(); + printBanner(); + putstr("Initializing timers...\r\n"); timer_foreach(initTimer); - Serial2.println("*** Done. Beginning timer test."); + putstr("Done. Running tests.\r\n"); + runTests(); + printBanner(); + putstr("Done testing timers.\r\n"); } void loop() { - Serial2.println("-----------------------------------------------------"); - - Serial2.println("Testing timer_get_count()/timer_set_count()"); - Serial2.print("TIMER1 count = "); - Serial2.println(timer_get_count(TIMER1)); - Serial2.println("timer_set_count(TIMER1, 1234)"); - timer_set_count(TIMER1, 1234); - Serial2.print("timer_get_count(TIMER1) = "); - Serial2.println(timer_get_count(TIMER1)); - - Serial2.println("-----------------------------------------------------"); - Serial2.println("Testing pause/resume; button roughly controls TIMER4"); - // when BUT is held down, TIMER4 is in the "pause" state and the - // timer doesn't increment, so the final counts should reflect the - // ratio of time that BUT was held down. - count3 = 0; - count4 = 0; - timer_set_mode(TIMER3, TIMER_CH1, TIMER_OUTPUT_COMPARE); - timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE); - timer_pause(TIMER3); - timer_pause(TIMER4); - timer_set_count(TIMER3, 0); - timer_set_count(TIMER4, 0); - timer_set_reload(TIMER3, 30000); - timer_set_reload(TIMER4, 30000); - timer_set_compare(TIMER3, 1, 1000); - timer_set_compare(TIMER4, 1, 1000); - timer_attach_interrupt(TIMER3, TIMER_CC1_INTERRUPT, handler3b); - timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b); - timer_resume(TIMER3); - timer_resume(TIMER4); - - Serial2.println("Testing for ~4 seconds..."); - for(int i = 0; i < 4000; i++) { - if (isButtonPressed()) { - timer_pause(TIMER4); - } else { - timer_resume(TIMER4); - } - delay(1); - } +} - timer_set_mode(TIMER3, TIMER_CH1, TIMER_DISABLED); - timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED); - - Serial2.print("TIMER3 count: "); - Serial2.println(timer_get_count(TIMER3)); - Serial2.print("TIMER4 count: "); - Serial2.println(timer_get_count(TIMER4)); - - Serial2.println("-----------------------------------------------------"); - Serial2.println("Testing setTimerPeriod()"); - testSetTimerPeriod(10); - testSetTimerPeriod(30000); - testSetTimerPeriod(300000); - testSetTimerPeriod(30000); - - Serial2.println("Sanity check (with hand-coded reload and prescaler for " - "72 MHz timers):"); - timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE); - timer_set_prescaler(TIMER4, 33); - timer_set_reload(TIMER4, 65454); - timer_pause(TIMER4); - timer_set_count(TIMER4, 0); - timer_set_compare(TIMER4, TIMER_CH1, 1); - timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b); - Serial2.println("Period 30000ms, wait 2 seconds..."); - count4 = 0; - timer_resume(TIMER4); - delay(2000); - timer_pause(TIMER4); - timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED); - Serial2.print("TIMER4 count: "); - Serial2.println(count4); - Serial2.println(" (Should be around 2sec/30000ms ~ 67)"); - - // Test all the individual timer channels - timer_foreach(testTimerChannels); +// +// Test routine implementations +// + +static void runTests(void) { + runTest("timer_get_count()/timer_set_count()", testGetAndSetCount); + runTest("timer_pause()/timer_resume()", testPauseAndResume); + runTest("capture/compare channels and interrupts", + testTimerChannels); } -void initTimer(timer_dev *dev) { - switch (dev->type) { - case TIMER_ADVANCED: - case TIMER_GENERAL: - Serial2.print("Initializing timer "); - Serial2.println(timerNumber(dev)); - for (int c = 1; c <= 4; c++) { - timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE); - } - Serial2.println("Done."); - break; - case TIMER_BASIC: - break; +static void runTest(const char description[], timer_test_t test) { + printBanner(); + putstr("Testing "); + putstr(description); + putstrln("."); + timer_foreach(test); +} + +static void testGetAndSetCount(timer_dev *dev) { + unsigned before, after; + unsigned val_to_set = 1234; + + timer_pause(dev); + before = timer_get_count(dev); + timer_set_count(dev, val_to_set); + after = timer_get_count(dev); + timer_resume(dev); + + if (after != val_to_set) { + puttimn(dev); + putstr(": "); + putstr("*** FAIL: get/set count for "); + puttimn(dev); + putstr("."); + putstr("Start count = "); + putudec(before); + putstr(". Count set to "); + putudec(val_to_set); + putstr(", and now count is = "); + putudec(after); + println(); + } else if (verbose) { + puttimn(dev); + putstr(": "); + putstrln("[ok]"); } } -void testSetTimerPeriod(uint32 period) { - timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE); - timer_set_compare(TIMER4, TIMER_CH1, 1); - setTimerPeriod(TIMER4, period); - timer_pause(TIMER4); - timer_set_count(TIMER4, 0); - timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b); - Serial2.println("Period "); - Serial2.print(period); - Serial2.print(" ms. Waiting 2 seconds..."); - count4 = 0; - timer_resume(TIMER4); - delay(2000); - timer_pause(TIMER4); - timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED); - Serial2.print("TIMER4 count: "); - Serial2.println(timer_get_count(TIMER4)); - Serial2.print(" (Should be around 2 sec / "); - Serial2.print(period); - Serial2.print(" ms = "); - Serial2.print(double(2) / period * 1000); - Serial2.println(", modulo delays due to interrupts)"); +// This hack works on all currently supported STM32 series, but you +// may need to do something smarter in the future. The assertions +// ensure that our assumptions hold for your target. +static timer_dev *getDifferentTimerOnSameBusAs(timer_dev *dev) { + rcc_clk_domain dev_domain = rcc_dev_clk(dev->clk_id); + ASSERT(RCC_APB1 == dev_domain || RCC_APB2 == dev_domain); + ASSERT(rcc_dev_clk(TIMER1->clk_id) == RCC_APB2); + ASSERT(rcc_dev_clk(TIMER2->clk_id) == RCC_APB1); + ASSERT(rcc_dev_clk(TIMER8->clk_id) == RCC_APB2); + ASSERT(rcc_dev_clk(TIMER3->clk_id) == RCC_APB1); + + if (dev->clk_id == RCC_TIMER1) { + return TIMER8; + } + if (dev->clk_id == RCC_TIMER2) { + return TIMER3; + } + return dev_domain == RCC_APB2 ? TIMER1 : TIMER2; } -int timerNumber(timer_dev *dev) { - switch (dev->clk_id) { - case RCC_TIMER1: - return 1; - case RCC_TIMER2: - return 2; - case RCC_TIMER3: - return 3; - case RCC_TIMER4: - return 4; -#ifdef STM32_HIGH_DENSITY - case RCC_TIMER5: - return 5; - case RCC_TIMER6: - return 6; - case RCC_TIMER7: - return 7; - case RCC_TIMER8: - return 8; -#endif - default: - ASSERT(0); - return 0; +// Rough test of pause and resume. +// +// Approximately half the time, dev is in the "pause" state and the +// timer doesn't increment, while another timer (`base_dev') on the +// same bus continues. dev and base_dev have identical start counts +// and prescalers. +// +// Since dev and base_dev share a bus (and thus a base clock), and we +// configure them to have the same prescaler and start count, the +// ratio of their end counts should be approximately 1 : 2. We check +// to make sure this is true, up to tolerance `epsilon'. +static void testPauseAndResume(timer_dev *dev) { + timer_dev *base_dev = getDifferentTimerOnSameBusAs(dev); + unsigned start_count = 0, reload = 65535; + // This prescaler should be enough to ensure that we don't + // overflow, while still giving us a reasonably large number of + // timer ticks. + uint16 prescaler = CYCLES_PER_MICROSECOND * 50; + double epsilon = .02; + + if (rcc_dev_clk(base_dev->clk_id) != rcc_dev_clk(dev->clk_id)) { + putstrln("*** ERROR: cannot run test. Bus info is messed up."); + return; + } + + // Pause and set up timers + timer_pause(base_dev); + timer_pause(dev); + timer_set_count(base_dev, start_count); + timer_set_count(dev, start_count); + timer_set_reload(base_dev, reload); + timer_set_reload(dev, reload); + timer_set_prescaler(base_dev, prescaler); + timer_set_prescaler(dev, prescaler); + timer_generate_update(base_dev); + timer_generate_update(dev); + + // Resume the timers and run the test + ASSERT(timer_get_count(base_dev) == start_count); + ASSERT(timer_get_count(dev) == start_count); + timer_resume(base_dev); + timer_resume(dev); + _delay(1000); + timer_pause(dev); + _delay(1000); + timer_pause(base_dev); + + // Check the results + unsigned dev_count = timer_get_count(dev); + unsigned base_count = timer_get_count(base_dev); + double count_ratio = ((double)dev_count / base_count); + bool fail = false; + if (count_ratio > 0.5 + epsilon || count_ratio < 0.5 - epsilon) { + fail = true; + } + if (fail || verbose) { + puttimn(dev); + putstr(" vs. "); + puttimn(base_dev); + putstr(": "); + if (fail) putstr("*** FAIL: "); + else putstr("[ok] "); + putstr("(dev = "); + putudec(dev_count); + putstr(") / (base = "); + putudec(base_count); + putstr(") = "); + // hack hack hack + putudec((int)count_ratio); + count_ratio -= (int)count_ratio; + putstr("."); + int cr_x_100 = (int)(count_ratio * 100); + int hundredths = cr_x_100 % 10; + cr_x_100 /= 10; + int tenths = cr_x_100 % 10; + putudec(tenths); + putudec(hundredths); + println(); } } -/* This function touches every channel of a given timer. The output - * ratios should reflect the ratios of the rate variables. It - * demonstrates that, over time, the actual timing rates get blown - * away by other system interrupts. */ -void testTimerChannels(timer_dev *dev) { - t = timerNumber(dev); - toggleLED(); - delay(100); - Serial2.println("-----------------------------------------------------"); +// This function touches every capture/compare channel of a given +// timer. The channel counts should be equal within a timer +// regardless of other interrupts on the system (note that this +// doesn't really test timers with only a single capture/compare +// channel; for that, you'll want to do visual inspection of timers +// that share a bus, in verbose mode). +static void testTimerChannels(timer_dev *dev) { switch (dev->type) { case TIMER_BASIC: - Serial2.print("NOT testing channels for basic timer "); - Serial2.println(t); - break; + v_putstr("Skipping basic timer "); + v_puttimn(dev); + v_println(); + return; case TIMER_ADVANCED: case TIMER_GENERAL: - Serial2.print("Testing channels for timer "); - Serial2.println(t); + // Set up + v_puttimn(dev); + v_println(); + v_putstr("\tchannels: "); + + timer_num = timerNumber(dev); timer_pause(dev); - count1 = count2 = count3 = count4 = 0; + count1 = 0; + count2 = 0; + count3 = 0; + count4 = 0; timer_set_reload(dev, 0xFFFF); timer_set_prescaler(dev, 1); for (int c = 1; c <= 4; c++) { - timer_set_compare(dev, c, 65535); - timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE); - timer_attach_interrupt(dev, c, handlers[c - 1]); + if (timer_has_cc_ch(dev, c)) { + v_putudec(c); + v_putstr("\t"); + timer_set_compare(dev, c, 0xFFFF); + timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE); + timer_attach_interrupt(dev, c, handlers[c - 1]); + } } + v_println(); + + // Run test + timer_generate_update(dev); timer_resume(dev); - delay(3000); + _delay(250); + timer_pause(dev); + + // Print results + v_putstr("\tcounts: "); + bool fail = false; + bool mismatched[4] = {false, false, false, false}; + int counts[4]; + counts[0] = count1; + counts[1] = count2; + counts[2] = count3; + counts[3] = count4; + bool first = true; + int first_count = -1; + for (int c = 1; c <= 4; c++) { + if (timer_has_cc_ch(dev, c)) { + if (first) { + first_count = counts[c - 1]; + first = false; + } + if (!first && (counts[c - 1] != first_count)) { + mismatched[c - 1] = true; + fail = true; + } + v_putudec(counts[c - 1]); + v_putstr("\t"); + } + } + v_println(); + if (fail) { + for (int i = 0; i < 4; i++) { + if (mismatched[i]) { + putstr("*** FAIL: mismatch on "); + puttimn(dev); + putstr(", channel "); + putudec(i + 1); + putstr(": expected "); + putudec(first_count); + putstr(", got "); + putudec(counts[i]); + println(); + } + } + } else { + puttimn(dev); + putstrln(" [ok]"); + } + v_println(); + + // Clean up for (int c = 1; c <= 4; c++) { - timer_set_mode(dev, c, TIMER_DISABLED); + if (timer_has_cc_ch(dev, c)) { + timer_set_mode(dev, c, TIMER_DISABLED); + } } - Serial2.print("Channel 1 count: "); Serial2.println(count1); - Serial2.print("Channel 2 count: "); Serial2.println(count2); - Serial2.print("Channel 3 count: "); Serial2.println(count3); - Serial2.print("Channel 4 count: "); Serial2.println(count4); break; } } -// FIXME [0.1.0] move some incarnation of this into timer.h -void setTimerPeriod(timer_dev *dev, uint32 period_us) { - if (!period_us) { - // FIXME handle this case - ASSERT(0); - return; - } +// +// Helper implementations +// - uint32 cycles = period_us * CYCLES_PER_MICROSECOND; - uint16 pre = (uint16)((cycles >> 16) + 1); - timer_set_prescaler(dev, pre); - timer_set_reload(dev, cycles / pre - 1); +static void _delay(uint32 msec) { + uint32 end = systick_uptime() + msec; + while (systick_uptime() < end) + ; } -void handler1(void) { - val1 += rate1; - timer_set_compare(timers[t], TIMER_CH1, val1); - count1++; +static void init_usart(usart_dev *dev, gpio_dev *gdev, uint8 tx, uint8 rx) { + usart_config_gpios_async(dev, gdev, rx, gdev, tx, 0); + usart_init(dev); + usart_set_baud_rate(dev, USART_USE_PCLK, COMM_USART_BAUD); + usart_enable(dev); } -void handler2(void) { - val2 += rate2; - timer_set_compare(timers[t], TIMER_CH2, val2); - count2++; +static bool timer_has_cc_ch(timer_dev *dev, int ch) { + ASSERT(1 <= ch && ch <= 4); + if (dev->type == TIMER_BASIC) + return false; + int tn = timerNumber(dev); + return (// TIM1-5 and 8 have all four channels + (tn <= 5 || tn == 8) || + // TIM9 and 12 only have channels 1 and 2 + ((tn == 9 || tn == 12) && ch <= 2) || + // All other general purpose timers only have channel 1 + (ch == 1)); } -void handler3(void) { - val3 += rate3; - timer_set_compare(timers[t], TIMER_CH3, val3); - count3++; +static void putstr(const char str[]) { + usart_putstr(COMM_USART, str); } -void handler4(void) { - val4 += rate4; - timer_set_compare(timers[t], TIMER_CH4, val4); - count4++; +static void println(void) { + putstr("\r\n"); } -void handler3b(void) { +static void putstrln(const char str[]) { + putstr(str); + println(); +} + +static void putudec(uint32 val) { + usart_putudec(COMM_USART, val); +} + +static void puttimn(timer_dev *dev) { + putstr("TIM"); + putudec(timerNumber(dev)); +} + +static void v_putstr(const char str[]) { + if (verbose) putstr(str); +} + +static void v_println() { + if (verbose) println(); +} + +__attribute__((unused)) /* (shut up, gcc) */ +static void v_putstrln(const char str[]) { + if (verbose) putstrln(str); +} + +static void v_putudec(uint32 val) { + if (verbose) putudec(val); +} + +static void v_puttimn(timer_dev *dev) { + if (verbose) puttimn(dev); +} + +// Used to visually separate output from different tests +static void printBanner(void) { + putstrln("-----------------------------------------------------"); +} + +static void initTimer(timer_dev *dev) { + v_puttimn(dev); + timer_init(dev); + switch (dev->type) { + case TIMER_ADVANCED: + case TIMER_GENERAL: + v_putstr(" channels "); + for (int c = 1; c <= 4; c++) { + if (timer_has_cc_ch(dev, c)) { + v_putudec(c); + v_putstr(" "); + timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE); + } + } + break; + case TIMER_BASIC: + break; + } + v_println(); +} + +static int timerNumber(timer_dev *dev) { + switch (dev->clk_id) { + case RCC_TIMER1: return 1; + case RCC_TIMER2: return 2; + case RCC_TIMER3: return 3; + case RCC_TIMER4: return 4; + case RCC_TIMER5: return 5; + case RCC_TIMER6: return 6; + case RCC_TIMER7: return 7; + case RCC_TIMER8: return 8; + case RCC_TIMER9: return 9; + case RCC_TIMER10: return 10; + case RCC_TIMER11: return 11; + case RCC_TIMER12: return 12; + case RCC_TIMER13: return 13; + case RCC_TIMER14: return 14; + default: + ASSERT(0); + return 0; + } +} + +// +// IRQ Handlers +// + +static void handler1(void) { + count1++; +} + +static void handler2(void) { + count2++; +} + +static void handler3(void) { count3++; } -void handler4b(void) { +static void handler4(void) { count4++; } +// +// init() and main() +// + __attribute__((constructor)) void premain() { init(); } diff --git a/examples/test-usart-dma.cpp b/examples/test-usart-dma.cpp index 5ff5b86..d10dc68 100644 --- a/examples/test-usart-dma.cpp +++ b/examples/test-usart-dma.cpp @@ -1,5 +1,5 @@ /** - * @file test-usart-dma.cpp + * @file examples/test-usart-dma.cpp * @author Marti Bolivar <mbolivar@leaflabs.com> * * Simple test of DMA used with a USART receiver. @@ -12,100 +12,188 @@ * * This example isn't very robust; don't use it in production. In * particular, since the buffer keeps filling (DMA_CIRC_MODE is set), - * if you keep typing after filling the buffer, you'll overwrite - * earlier bytes; this may happen before those earlier bytes are done - * printing. + * if you keep sending characters after filling the buffer, you'll + * overwrite earlier bytes; this may happen before those earlier bytes + * are done printing. (Typing quickly and seeing how it affects the + * output is a fun way to make sense of how the interrupts and the + * main thread of execution interleave.) * * This code is released into the public domain. */ -#include "dma.h" -#include "usart.h" -#include "gpio.h" +#include <libmaple/dma.h> +#include <libmaple/usart.h> +#include <libmaple/gpio.h> -#include "wirish.h" +#include <wirish/wirish.h> -#define BAUD 9600 +/* + * Configuration and state + */ -#define USART USART2 -#define USART_HWSER Serial2 +// Serial port and DMA configuration. You can change these to suit +// your purposes. +HardwareSerial *serial = &Serial2; #define USART_DMA_DEV DMA1 -#define USART_RX_DMA_CHANNEL DMA_CH6 -#define USART_TX BOARD_USART2_TX_PIN -#define USART_RX BOARD_USART2_RX_PIN +#if STM32_MCU_SERIES == STM32_SERIES_F1 +// On STM32F1 microcontrollers (like what's on Maple and Maple Mini), +// dma tubes are channels. +#define USART_RX_DMA_TUBE DMA_CH6 +#elif (STM32_MCU_SERIES == STM32_SERIES_F2 || \ + STM32_MCU_SERIES == STM32_SERIES_F4) +// On STM32F2 and STM32F4 microcontrollers (Maple 2 will have an F4), +// dma tubes are streams. +#define USART_RX_DMA_TUBE DMA_S5 +#else +#error "unsupported stm32 series" +#endif +// The serial port will make a DMA request each time it receives data. +// This is the dma_request_src we use to tell the DMA tube to handle +// that DMA request. +#define USART_DMA_REQ_SRC DMA_REQ_SRC_USART2_RX +#define BAUD 9600 -#define BUF_SIZE 8 -uint8 rx_buf[BUF_SIZE]; +// This will store the DMA configuration for USART RX. +dma_tube_config tube_config; -dma_irq_cause irq_cause; +// This will store received USART characters. +#define BUF_SIZE 20 +char rx_buf[BUF_SIZE]; +// The interrupt handler, rx_dma_irq(), sets this to 1. volatile uint32 irq_fired = 0; +// Used to store DMA interrupt status register (ISR) bits inside +// rx_dma_irq(). This helps explain what's going on inside loop(); see +// comments below. +volatile uint32 isr = 0; + +/* + * Helper functions + */ + +// This is our DMA interrupt handler. +void rx_dma_irq(void) { + irq_fired = 1; + isr = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_TUBE); +} + +// Configure the USART receiver for use with DMA: +// 1. Turn it on. +// 2. Set the "DMA request on RX" bit in USART_CR3 (USART_CR3_DMAR). +void setup_usart(void) { + serial->begin(BAUD); + usart_dev *serial_dev = serial->c_dev(); + serial_dev->regs->CR3 = USART_CR3_DMAR; +} + +// Set up our dma_tube_config structure. (We could have done this +// above, when we declared tube_config, but having this function makes +// it easier to explain what's going on). +void setup_tube_config(void) { + // We're receiving from the USART data register. serial->c_dev() + // returns a pointer to the libmaple usart_dev for that serial + // port, so this is a pointer to its data register. + tube_config.tube_src = &serial->c_dev()->regs->DR; + // We're only interested in the bottom 8 bits of that data register. + tube_config.tube_src_size = DMA_SIZE_8BITS; + // We're storing to rx_buf. + tube_config.tube_dst = rx_buf; + // rx_buf is a char array, and a "char" takes up 8 bits on STM32. + tube_config.tube_dst_size = DMA_SIZE_8BITS; + // Only fill BUF_SIZE - 1 characters, to leave a null byte at the end. + tube_config.tube_nr_xfers = BUF_SIZE - 1; + // Flags: + // - DMA_CFG_DST_INC so we start at the beginning of rx_buf and + // fill towards the end. + // - DMA_CFG_CIRC so we go back to the beginning and start over when + // rx_buf fills up. + // - DMA_CFG_CMPLT_IE to turn on interrupts on transfer completion. + tube_config.tube_flags = DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE; + // Target data: none. It's important to set this to NULL if you + // don't have any special (microcontroller-specific) configuration + // in mind, which we don't. + tube_config.target_data = NULL; + // DMA request source. + tube_config.tube_req_src = USART_DMA_REQ_SRC; +} + +// Configure the DMA controller to serve DMA requests from the USART. +void setup_dma_xfer(void) { + // First, turn it on. + dma_init(USART_DMA_DEV); + // Next, configure it by calling dma_tube_cfg(), and check to make + // sure it succeeded. DMA tubes have many restrictions on their + // configuration, and there are configurations which work on some + // types of STM32 but not others. libmaple tries hard to make + // things just work, but checking the return status is important! + int status = dma_tube_cfg(USART_DMA_DEV, USART_RX_DMA_TUBE, &tube_config); + ASSERT(status == DMA_TUBE_CFG_SUCCESS); + // Now we'll perform any other configuration we want. For this + // example, we attach an interrupt handler. + dma_attach_interrupt(USART_DMA_DEV, USART_RX_DMA_TUBE, rx_dma_irq); + // Turn on the DMA tube. It will now begin serving requests. + dma_enable(USART_DMA_DEV, USART_RX_DMA_TUBE); +} -void init_usart(void); -void init_dma_xfer(void); -void rx_dma_irq(void); +/* + * setup() and loop() + */ void setup(void) { pinMode(BOARD_LED_PIN, OUTPUT); - - init_dma_xfer(); - init_usart(); + setup_tube_config(); + setup_dma_xfer(); + setup_usart(); } void loop(void) { toggleLED(); delay(100); - dma_channel_reg_map *ch_regs = dma_channel_regs(USART_DMA_DEV, - USART_RX_DMA_CHANNEL); + // See if the interrupt handler got called since the last time we + // checked. if (irq_fired) { - USART_HWSER.println("** IRQ **"); + serial->println("** IRQ **"); + // Notice how the interrupt status register (ISR) bits show + // transfer complete _and_ half-complete here, but the ISR + // bits we print next will be zero. That's because the + // variable "isr" gets set _inside_ rx_dma_irq(). After it + // exits, libmaple cleans up by clearing the tube's ISR + // bits. (If it didn't, and we forgot to, the interrupt would + // repeatedly fire forever.) + serial->print("ISR bits: 0x"); + serial->println(isr, HEX); irq_fired = 0; } - USART_HWSER.print("["); - USART_HWSER.print(millis()); - USART_HWSER.print("]\tISR bits: 0x"); - uint8 isr_bits = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_CHANNEL); - USART_HWSER.print(isr_bits, HEX); - USART_HWSER.print("\tCCR: 0x"); - USART_HWSER.print(ch_regs->CCR, HEX); - USART_HWSER.print("\tCNDTR: 0x"); - USART_HWSER.print(ch_regs->CNDTR, HEX); - USART_HWSER.print("\tBuffer contents: "); - for (int i = 0; i < BUF_SIZE; i++) { - USART_HWSER.print('\''); - USART_HWSER.print(rx_buf[i]); - USART_HWSER.print('\''); - if (i < BUF_SIZE - 1) USART_HWSER.print(", "); - } - USART_HWSER.println(); + + // Print the ISR bits. + // + // Notice that the "transfer half-complete" ISR flag gets set when + // we reach the rx_buf half-way point. This is true even though we + // don't tell the DMA controller to interrupt us on a + // half-complete transfer. That is, the ISR bits get set at the + // right times no matter what; we just don't get interrupted + // unless we asked. (If an error or other problem occurs, the + // relevant ISR bits will get set in the same way). + serial->print("["); + serial->print(millis()); + serial->print("]\tISR bits: 0x"); + uint8 isr_bits = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_TUBE); + serial->print(isr_bits, HEX); + + // Print the contents of rx_buf. If you keep typing after it fills + // up, the new characters will overwrite the old ones, thanks to + // DMA_CIRC_MODE. + serial->print("\tCharacter buffer contents: '"); + serial->print(rx_buf); + serial->println("'"); if (isr_bits == 0x7) { - USART_HWSER.println("** Clearing ISR bits."); - dma_clear_isr_bits(USART_DMA_DEV, USART_RX_DMA_CHANNEL); + serial->println("** Clearing ISR bits."); + dma_clear_isr_bits(USART_DMA_DEV, USART_RX_DMA_TUBE); } } -/* Configure USART receiver for use with DMA */ -void init_usart(void) { - USART_HWSER.begin(BAUD); - USART->regs->CR3 = USART_CR3_DMAR; -} - -/* Configure DMA transmission */ -void init_dma_xfer(void) { - dma_init(USART_DMA_DEV); - dma_setup_transfer(USART_DMA_DEV, USART_RX_DMA_CHANNEL, - &USART->regs->DR, DMA_SIZE_8BITS, - rx_buf, DMA_SIZE_8BITS, - (DMA_MINC_MODE | DMA_CIRC_MODE | DMA_TRNS_CMPLT)); - dma_set_num_transfers(USART_DMA_DEV, USART_RX_DMA_CHANNEL, BUF_SIZE); - dma_attach_interrupt(USART_DMA_DEV, USART_RX_DMA_CHANNEL, rx_dma_irq); - dma_enable(USART_DMA_DEV, USART_RX_DMA_CHANNEL); -} - -void rx_dma_irq(void) { - irq_fired = true; -} +// ------- init() and main() -------------------------------------------------- // Force init to be called *first*, i.e. before static object allocation. // Otherwise, statically allocated objects that need libmaple may fail. diff --git a/examples/vga-leaf.cpp b/examples/vga-leaf.cpp index f31dc87..5159956 100644 --- a/examples/vga-leaf.cpp +++ b/examples/vga-leaf.cpp @@ -32,7 +32,7 @@ // FIXME: generalize for Native and Mini -#include "wirish.h" +#include <wirish/wirish.h> // Pinouts -- you also must change the GPIO macros below if you change // these diff --git a/examples/vga-scope.cpp b/examples/vga-scope.cpp index b5fa8a5..8730cf0 100644 --- a/examples/vga-scope.cpp +++ b/examples/vga-scope.cpp @@ -35,8 +35,8 @@ Marti Bolivar <mbolivar@leaflabs.com> */ -#include "wirish.h" -#include "systick.h" +#include <wirish/wirish.h> +#include <libmaple/systick.h> // FIXME: generalize for Native and Mini |