diff options
Diffstat (limited to 'wirish')
37 files changed, 2386 insertions, 1589 deletions
| diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp index 354663e..d0e32c3 100644 --- a/wirish/HardwareTimer.cpp +++ b/wirish/HardwareTimer.cpp @@ -22,205 +22,125 @@   * THE SOFTWARE.   *****************************************************************************/ -/* - * wirish timer class to manage the four 16-bit timer peripherals - */ - -#include "wirish.h"  #include "HardwareTimer.h" +#include "boards.h"             // for CYCLES_PER_MICROSECOND +#include "wirish_math.h" -HardwareTimer::HardwareTimer(timer_dev_num timerNum) { -    ASSERT(timerNum != TIMER_INVALID); +// TODO [0.1.0] Remove deprecated pieces -    this->timerNum = timerNum; -} +#ifdef STM32_MEDIUM_DENSITY +#define NR_TIMERS 4 +#elif defined(STM32_HIGH_DENSITY) +#define NR_TIMERS 8 +#else +#error "Unsupported density" +#endif -void HardwareTimer::resume(void) { -    timer_resume(this->timerNum); +#define MAX_RELOAD ((1 << 16) - 1) + +HardwareTimer::HardwareTimer(uint8 timerNum) { +    if (timerNum > NR_TIMERS) { +        ASSERT(0); +    } +    timer_dev *devs[] = { +        TIMER1, +        TIMER2, +        TIMER3, +        TIMER4, +#ifdef STM32_HIGH_DENSITY +        TIMER5, +        TIMER6, +        TIMER7, +        TIMER8, +#endif +    }; +    this->dev = devs[timerNum - 1];  }  void HardwareTimer::pause(void) { -    timer_pause(this->timerNum); +    timer_pause(this->dev);  } -uint16 HardwareTimer::getPrescaleFactor(void) { -    return timer_get_prescaler(this->timerNum) + 1; +void HardwareTimer::resume(void) { +    timer_resume(this->dev); +} + +uint32 HardwareTimer::getPrescaleFactor(void) { +    return timer_get_prescaler(this->dev) + 1;  } -void HardwareTimer::setPrescaleFactor(uint16 factor) { -    // The prescaler register is zero-indexed -    timer_set_prescaler(this->timerNum, factor-1); +void HardwareTimer::setPrescaleFactor(uint32 factor) { +    timer_set_prescaler(this->dev, (uint16)(factor - 1));  }  uint16 HardwareTimer::getOverflow() { -    return timer_get_reload(this->timerNum); +    return timer_get_reload(this->dev);  }  void HardwareTimer::setOverflow(uint16 val) { -    timer_set_reload(this->timerNum, val); +    timer_set_reload(this->dev, val);  }  uint16 HardwareTimer::getCount(void) { -    return timer_get_count(this->timerNum); +    return timer_get_count(this->dev);  }  void HardwareTimer::setCount(uint16 val) {      uint16 ovf = this->getOverflow(); -    timer_set_count(this->timerNum, min(val, ovf)); +    timer_set_count(this->dev, min(val, ovf));  } +// FIXME [0.0.10 beta] test!  uint16 HardwareTimer::setPeriod(uint32 microseconds) {      // Not the best way to handle this edge case? -    if(!microseconds) { -        setPrescaleFactor(1); -        setOverflow(1); +    if (!microseconds) { +        this->setPrescaleFactor(1); +        this->setOverflow(1);          return this->getOverflow();      } -    uint32 cycles = microseconds * CYCLES_PER_MICROSECOND; - -    // With a prescale factor of 1, there are CYCLES_PER_MICROSECOND -    // counts/ms -    uint16 ps = (uint16)((cycles >> 16) + 1); -    setPrescaleFactor(ps); - -    // Finally, this overflow will always be less than 65536 -    setOverflow((cycles/ps) - 1); - -    return this->getOverflow(); -} - -inline void HardwareTimer::setChannelMode(int channel, TimerMode mode) { -    timer_set_mode(this->timerNum, channel, mode); -} - -void HardwareTimer::setChannel1Mode(TimerMode mode) { -    this->setChannelMode(1, mode); -} - -void HardwareTimer::setChannel2Mode(TimerMode mode) { -    this->setChannelMode(2, mode); -} - -void HardwareTimer::setChannel3Mode(TimerMode mode) { -    this->setChannelMode(3, mode); -} - -void HardwareTimer::setChannel4Mode(TimerMode mode) { -    this->setChannelMode(4, mode); -} - -inline uint16 HardwareTimer::getCompare(int channel) { -    return timer_get_compare_value(this->timerNum, channel); -} - -uint16 HardwareTimer::getCompare1() { -    return this->getCompare(1); -} -uint16 HardwareTimer::getCompare2() { -    return this->getCompare(2); +    uint32 period_cyc = microseconds * CYCLES_PER_MICROSECOND; +    uint16 prescaler = (uint16)(period_cyc / MAX_RELOAD); +    uint16 overflow = (uint16)round(period_cyc / prescaler); +    this->setPrescaleFactor(prescaler); +    this->setOverflow(overflow); +    return overflow;  } -uint16 HardwareTimer::getCompare3() { -    return this->getCompare(3); +void HardwareTimer::setMode(int channel, timer_mode mode) { +    timer_set_mode(this->dev, (uint8)channel, (timer_mode)mode);  } -uint16 HardwareTimer::getCompare4() { -    return this->getCompare(4); +uint16 HardwareTimer::getCompare(int channel) { +    return timer_get_compare(this->dev, (uint8)channel);  } -inline void HardwareTimer::setCompare(int channel, uint16 val) { +void HardwareTimer::setCompare(int channel, uint16 val) {      uint16 ovf = this->getOverflow(); -    timer_set_compare_value(this->timerNum, channel, min(val, ovf)); +    timer_set_compare(this->dev, (uint8)channel, min(val, ovf));  } -void HardwareTimer::setCompare1(uint16 val) { -    this->setCompare(1, val); +void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) { +    timer_attach_interrupt(this->dev, (uint8)channel, handler);  } -void HardwareTimer::setCompare2(uint16 val) { -    this->setCompare(2, val); +void HardwareTimer::detachInterrupt(int channel) { +    timer_detach_interrupt(this->dev, (uint8)channel);  } -void HardwareTimer::setCompare3(uint16 val) { -    this->setCompare(3, val); +void HardwareTimer::refresh(void) { +    timer_generate_update(this->dev);  } -void HardwareTimer::setCompare4(uint16 val) { -    this->setCompare(4, val); -} - -inline void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) { -    timer_attach_interrupt(this->timerNum, channel, handler); -} - -void HardwareTimer::attachCompare1Interrupt(voidFuncPtr handler) { -    this->attachInterrupt(1, handler); -} - -void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) { -    this->attachInterrupt(2, handler); -} - -void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) { -    this->attachInterrupt(3, handler); -} - -void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) { -    this->attachInterrupt(4, handler); -} - -inline void HardwareTimer::detachInterrupt(int channel) { -    timer_detach_interrupt(this->timerNum, channel); -} - -void HardwareTimer::detachCompare1Interrupt(void) { -    this->detachInterrupt(1); -} - -void HardwareTimer::detachCompare2Interrupt(void) { -    this->detachInterrupt(2); -} - -void HardwareTimer::detachCompare3Interrupt(void) { -    this->detachInterrupt(3); -} - -void HardwareTimer::detachCompare4Interrupt(void) { -    this->detachInterrupt(4); -} +/* -- Deprecated predefined instances -------------------------------------- */ -void HardwareTimer::generateUpdate(void) { -    timer_generate_update(this->timerNum); -} - - -HardwareTimer Timer1(TIMER1); -HardwareTimer Timer2(TIMER2); -HardwareTimer Timer3(TIMER3); -HardwareTimer Timer4(TIMER4); -#if NR_TIMERS >= 8 -HardwareTimer Timer5(TIMER5);    // High-density devices only -HardwareTimer Timer8(TIMER8);    // High-density devices only +HardwareTimer Timer1(1); +HardwareTimer Timer2(2); +HardwareTimer Timer3(3); +HardwareTimer Timer4(4); +#ifdef STM32_HIGH_DENSITY +HardwareTimer Timer5(5); +HardwareTimer Timer6(6); +HardwareTimer Timer7(7); +HardwareTimer Timer8(8);  #endif - -HardwareTimer* getTimer(timer_dev_num timerNum) { -    switch (timerNum) { -    case TIMER1: -        return &Timer1; -    case TIMER2: -        return &Timer2; -    case TIMER3: -        return &Timer3; -    case TIMER4: -        return &Timer4; -#if NR_TIMERS >= 8 -    case TIMER5: -        return &Timer5; -    case TIMER8: -        return &Timer8; -#endif -    default: -        return 0; -    } -} diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h index 4034b1f..fd8ca9a 100644 --- a/wirish/HardwareTimer.h +++ b/wirish/HardwareTimer.h @@ -23,66 +23,45 @@   *****************************************************************************/  /** - *  @brief wirish timer class to manage the four 16-bit timer peripherals + *  @brief Wirish timer class.   */  #ifndef _HARDWARETIMER_H_  #define _HARDWARETIMER_H_ -#include "timers.h" +// TODO [0.1.0] Remove deprecated pieces, pick a better API + +#include "timer.h" + +/** Timer mode. */ +typedef timer_mode TimerMode; + +/** @brief Deprecated; use TIMER_OUTPUT_COMPARE instead. */ +#define TIMER_OUTPUTCOMPARE TIMER_OUTPUT_COMPARE  /** - * Interface to one of the 16-bit timer peripherals. - * - * User code should not instantiate this class directly; instead, use - * one of the predefined Timer<n> instances (Timer1, Timer2, etc.). - * - * HardwareTimer instances can be configured to generate periodic or - * delayed events with minimal work done by the microcontroller.  Each - * timer maintains a single 16-bit count that can be configured with a - * prescaler and overflow value. - * - * By default, a timer's counter is incremented once per clock cycle. - * The prescaler acts as a divider of the 72MHz Maple system clock; - * without prescaling, the timer's count would reach 65535 (2**16-1) - * and roll over over 1000 times per second. - * - * The overflow value is the maximum value the counter will reach.  It - * defaults to 65535; smaller values will cause the counter to reset - * more frequently. + * @brief Interface to one of the 16-bit timer peripherals.   */  class HardwareTimer { - private: -    timer_dev_num timerNum; - - public: -    HardwareTimer(timer_dev_num timer_num); +private: +    timer_dev *dev; +public:      /** -     * Return this timer's device number. For example, -     *  Timer1.getTimerNum() == TIMER1 +     * @brief Construct a new HardwareTimer instance. +     * @param timerNum number of the timer to control.       */ -    timer_dev_num getTimerNum() { return timerNum; } +    HardwareTimer(uint8 timerNum);      /** -     * Stop the counter, without affecting its configuration. -     * -     * The timer will no longer count or fire interrupts after this -     * function is called, until it is resumed.  This function is -     * useful during timer setup periods, in order to prevent -     * interrupts from firing before the timer is fully configured. -     * -     * Note that there is some function call overhead associated with -     * this method, so using it in concert with -     * HardwareTimer::resume() is not a robust way to align multiple -     * timers to the same count value. +     * @brief Stop the counter, without affecting its configuration.       *       * @see HardwareTimer::resume()       */      void pause(void);      /** -     * Resume a paused timer, without affecting its configuration. +     * @brief Resume a paused timer, without affecting its configuration.       *       * The timer will resume counting and firing interrupts as       * appropriate. @@ -97,66 +76,51 @@ class HardwareTimer {      void resume(void);      /** -     * Returns the timer's prescale factor. +     * @brief Get the timer's prescale factor. +     * @return Timer prescaler, from 1 to 65,536.       * @see HardwareTimer::setPrescaleFactor()       */ -    uint16 getPrescaleFactor(); +    uint32 getPrescaleFactor();      /** -     * Set the timer's prescale factor. +     * @brief Set the timer's prescale factor.       * -     * The prescaler acts as a clock divider to slow down the rate at -     * which the counter increments. +     * The new value won't take effect until the next time the counter +     * overflows.  You can force the counter to reset using +     * HardwareTimer::refresh().       * -     * For example, the system clock rate is 72MHz, so the counter -     * will reach 65535 in (13.89 nanoseconds) * (65535 counts) = -     * (910.22 microseconds), or about a thousand times a second. If -     * the prescaler equals 1098, then the clock rate is effectively -     * 65.56KHz, and the counter will reach 65536 in (15.25 -     * microseconds) * (65536 counts) = (0.999 seconds), or about once -     * per second. -     * -     * The HardwareTimer::setPeriod() method may also be used as a -     * convenient alternative. -     * -     * @param factor The new prescale value to set. -     * @see HardwareTimer::setPeriod() +     * @param factor The new prescale value to set, from 1 to 65,536. +     * @see HardwareTimer::refresh()       */ -    void setPrescaleFactor(uint16 factor); +    void setPrescaleFactor(uint32 factor);      /** -     * Gets the timer overflow value. +     * @brief Get the timer overflow value.       * @see HardwareTimer::setOverflow()       */      uint16 getOverflow();      /** -     * Sets the timer overflow (or "reload") value. +     * @brief Set the timer overflow (or "reload") value.       * -     * When the timer's counter reaches this, value it resets to -     * zero. Its default value is 65535 (the largest unsigned 16-bit -     * integer); setting the overflow to anything lower will cause -     * interrupts to be called more frequently (see the setPeriod() -     * function below for a shortcut). This number sets the maximum -     * value for the channel compare values. +     * The new value won't take effect until the next time the counter +     * overflows.  You can force the counter to reset using +     * HardwareTimer::refresh().       *       * @param val The new overflow value to set +     * @see HardwareTimer::refresh()       */      void setOverflow(uint16 val);      /** -     * Retrieve the current timer count. +     * @brief Get the current timer count.       *       * @return The timer's current count value       */      uint16 getCount(void);      /** -     * Set the current timer count. -     * -     * Note that there is some function call overhead associated with -     * calling this method, so using it is not a robust way to get -     * multiple timers to share a count value. +     * @brief Set the current timer count.       *       * @param val The new count value to set.  If this value exceeds       *            the timer's overflow value, it is truncated to the @@ -165,143 +129,50 @@ class HardwareTimer {      void setCount(uint16 val);      /** -     * Configure the prescaler and overflow values to generate a timer +     * @brief Set the timer's period in microseconds. +     * +     * Configures the prescaler and overflow values to generate a timer       * reload with a period as close to the given number of       * microseconds as possible.       * -     * The return value is the overflow, which may be used to set -     * channel compare values.  However, if a clock that fires an -     * interrupt every given number of microseconds is all that is -     * desired, and the relative "phases" are unimportant, channel -     * compare values may all be set to 1. -     * -     * @param microseconds the desired period of the timer. -     * @return the overflow value (and thus, the largest value that can be -     *         set as a compare). +     * @param microseconds The desired period of the timer.  This must be +     *                     greater than zero. +     * @return The new overflow value.       */      uint16 setPeriod(uint32 microseconds);      /** -     * Set the given channel of this timer to the given mode. -     * +     * @brief Configure a timer channel's mode.       * @param channel Timer channel, from 1 to 4       * @param mode Mode to set       */ -    void setChannelMode(int channel, TimerMode mode); - -    /** -     * Set channel 1 of this timer to the given mode. -     * -     * Note: Timer1.setChannel1Mode(TIMER_PWM) may not work as -     * expected; if you want PWM functionality on a channel make sure -     * you don't set it to something else! -     * -     * @see TimerMode -     */ -    void setChannel1Mode(TimerMode mode); - -    /** -     * Set channel 2 of this timer to the given mode. -     * @see TimerMode -     */ -    void setChannel2Mode(TimerMode mode); - -    /** -     * Set channel 3 of this timer to the given mode. -     * @see TimerMode -     */ -    void setChannel3Mode(TimerMode mode); - -    /** -     * Set channel 4 of this timer to the given mode. -     * @see TimerMode -     */ -    void setChannel4Mode(TimerMode mode); +    void setMode(int channel, timer_mode mode);      /** -     * Gets the compare value for the given channel. +     * @brief Get the compare value for the given channel.       * @see HardwareTimer::setCompare()       */      uint16 getCompare(int channel); -    /** Equivalent to getCompare(1) */ -    uint16 getCompare1(); - -    /** Equivalent to getCompare(2) */ -    uint16 getCompare2(); - -    /** Equivalent to getCompare(3) */ -    uint16 getCompare3(); - -    /** Equivalent to getCompare(4) */ -    uint16 getCompare4(); -      /** -     * Sets the compare value for the given channel. -     * -     * When the counter reaches this value the interrupt for this -     * channel will fire if the channel mode is TIMER_OUTPUTCOMPARE -     * and an interrupt is attached. -     * -     * By default, this only changes the relative offsets between -     * events on a single timer ("phase"); they don't control the -     * frequency with which they occur. However, a common trick is to -     * increment the compare value manually in the interrupt handler -     * so that the event will fire again after the increment -     * period. There can be a different increment value for each -     * channel, so this trick allows events to be programmed at 4 -     * different rates on a single timer. Note that function call -     * overheads mean that the smallest increment rate is at least a -     * few microseconds. +     * @brief Set the compare value for the given channel.       *       * @param channel the channel whose compare to set, from 1 to 4.       * @param compare The compare value to set.  If greater than this       *                timer's overflow value, it will be truncated to       *                the overflow value.       * -     * @see TimerMode -     * @see HardwareTimer::setChannelMode() +     * @see timer_mode +     * @see HardwareTimer::setMode()       * @see HardwareTimer::attachInterrupt()       */      void setCompare(int channel, uint16 compare);      /** -     * Equivalent to setCompare(1, compare). -     */ -    void setCompare1(uint16 compare); - -    /** -     * Equivalent to setCompare(2, compare). -     */ -    void setCompare2(uint16 compare); - -    /** -     * Equivalent to setCompare(3, compare). -     */ -    void setCompare3(uint16 compare); - -    /** -     * Equivalent to setCompare(4, compare). -     */ -    void setCompare4(uint16 compare); - -    /** -     * Attach an interrupt handler to the given channel.  This -     * interrupt handler will be called when the timer's counter -     * reaches the given channel compare value. -     * -     * The argument should be a function which takes no arguments and -     * has no return value; i.e. it should have signature +     * @brief Attach an interrupt handler to the given channel.       * -     *     void (*handler)(void); -     * -     * Note: The function (often called an interrupt service routine, -     * or ISR) should attempt to return as quickly as possible. -     * Blinking the LED, some logic, PWM updates, and Serial writes -     * are fine; writing to SerialUSB or waiting for user input can -     * take a long time and other compare interrupts won't fire. Tip: -     * if you have a delay() in your interrupt routine, you're probably -     * doing it wrong. +     * This interrupt handler will be called when the timer's counter +     * reaches the given channel compare value.       *       * @param channel the channel to attach the ISR to, from 1 to 4.       * @param handler The ISR to attach to the given channel. @@ -310,32 +181,10 @@ class HardwareTimer {      void attachInterrupt(int channel, voidFuncPtr handler);      /** -     * Equivalent to attachCompareInterrupt(1, handler). -     * @see HardwareTimer::attachCompareInterrupt() -     */ -    void attachCompare1Interrupt(voidFuncPtr handler); - -    /** -     * Equivalent to attachCompareInterrupt(2, handler). -     * @see HardwareTimer::attachCompareInterrupt() -     */ -    void attachCompare2Interrupt(voidFuncPtr handler); - -    /** -     * Equivalent to attachCompareInterrupt(3, handler). -     * @see HardwareTimer::attachCompareInterrupt() -     */ -    void attachCompare3Interrupt(voidFuncPtr handler); - -    /** -     * Equivalent to attachCompareInterrupt(4, handler). -     * @see HardwareTimer::attachCompareInterrupt() -     */ -    void attachCompare4Interrupt(voidFuncPtr handler); - -    /** -     * Remove the interrupt handler attached to the given channel, if -     * any.  The handler will no longer be called by this timer. +     * @brief Remove the interrupt handler attached to the given +     *        channel, if any. +     * +     * The handler will no longer be called by this timer.       *       * @param channel the channel whose interrupt to detach, from 1 to 4.       * @see HardwareTimer::attachInterrupt() @@ -343,71 +192,138 @@ class HardwareTimer {      void detachInterrupt(int channel);      /** -     * Equivalent to detachInterrupt(1). -     * @see HardwareTimer::detachInterrupt() +     * @brief Reset the counter, and update the prescaler and overflow +     *        values. +     * +     * This will reset the counter to 0 in upcounting mode (the +     * default).  It will also update the timer's prescaler and +     * overflow, if you have set them up to be changed using +     * HardwareTimer::setPrescaleFactor() or +     * HardwareTimer::setOverflow(). +     * +     * @see HardwareTimer::setPrescaleFactor() +     * @see HardwareTimer::setOverflow()       */ -    void detachCompare1Interrupt(void); +    void refresh(void); -    /** -     * Equivalent to detachInterrupt(2). -     * @see HardwareTimer::detachInterrupt() -     */ -    void detachCompare2Interrupt(void); +    /* -- Deprecated methods ----------------------------------------------- */ -    /** -     * Equivalent to detachInterrupt(3). -     * @see HardwareTimer::detachInterrupt() -     */ -    void detachCompare3Interrupt(void); +    /** @brief Deprecated; use setMode(channel, mode) instead. */ +    void setChannelMode(int channel, timer_mode mode) { +        setMode(channel, mode); +    } -    /** -     * Equivalent to detachInterrupt(4). -     * @see HardwareTimer::detachInterrupt() -     */ -    void detachCompare4Interrupt(void); +    /** @brief Deprecated; use setMode(TIMER_CH1, mode) instead. */ +    void setChannel1Mode(timer_mode mode) { setMode(TIMER_CH1, mode); } -    /** -     * Re-initializes the counter (to 0 in upcounting mode, which is -     * the default), and generates an update of the prescale and -     * overflow registers. -     */ -    void generateUpdate(void); +    /** @brief Deprecated; use setMode(TIMER_CH2, mode) instead. */ +    void setChannel2Mode(timer_mode mode) { setMode(TIMER_CH2, mode); } + +    /** @brief Deprecated; use setMode(TIMER_CH3, mode) instead. */ +    void setChannel3Mode(timer_mode mode) { setMode(TIMER_CH3, mode); } + +    /** @brief Deprecated; use setMode(TIMER_CH4, mode) instead. */ +    void setChannel4Mode(timer_mode mode) { setMode(TIMER_CH4, mode); } + +    /** @brief Deprecated; use return getCompare(TIMER_CH1) instead. */ +    uint16 getCompare1() { return getCompare(TIMER_CH1); } + +    /** @brief Deprecated; use return getCompare(TIMER_CH2) instead. */ +    uint16 getCompare2() { return getCompare(TIMER_CH2); } + +    /** @brief Deprecated; use return getCompare(TIMER_CH3) instead. */ +    uint16 getCompare3() { return getCompare(TIMER_CH3); } + +    /** @brief Deprecated; use return getCompare(TIMER_CH4) instead. */ +    uint16 getCompare4() { return getCompare(TIMER_CH4); } + +    /** @brief Deprecated; use setCompare(TIMER_CH1, compare) instead. */ +    void setCompare1(uint16 compare) { setCompare(TIMER_CH1, compare); } + +    /** @brief Deprecated; use setCompare(TIMER_CH2, compare) instead. */ +    void setCompare2(uint16 compare) { setCompare(TIMER_CH2, compare); } + +    /** @brief Deprecated; use setCompare(TIMER_CH3, compare) instead. */ +    void setCompare3(uint16 compare) { setCompare(TIMER_CH3, compare); } + +    /** @brief Deprecated; use setCompare(TIMER_CH4, compare) instead. */ +    void setCompare4(uint16 compare) { setCompare(TIMER_CH4, compare); } + +    /** @brief Deprecated; use attachInterrupt(TIMER_CH1, handler) instead. */ +    void attachCompare1Interrupt(voidFuncPtr handler) { +        attachInterrupt(TIMER_CH1, handler); +    } + +    /** @brief Deprecated; use attachInterrupt(TIMER_CH2, handler) instead. */ +    void attachCompare2Interrupt(voidFuncPtr handler) { +        attachInterrupt(TIMER_CH2, handler); +    } + +    /** @brief Deprecated; use attachInterrupt(TIMER_CH3, handler) instead. */ +    void attachCompare3Interrupt(voidFuncPtr handler) { +        attachInterrupt(TIMER_CH3, handler); +    } + +    /** @brief Deprecated; use attachInterrupt(TIMER_CH4, handler) instead. */ +    void attachCompare4Interrupt(voidFuncPtr handler) { +        attachInterrupt(TIMER_CH4, handler); +    } + +    /** @brief Deprecated; use detachInterrupt(TIMER_CH1) instead. */ +    void detachCompare1Interrupt(void) { detachInterrupt(TIMER_CH1); } + +    /** @brief Deprecated; use detachInterrupt(TIMER_CH2) instead. */ +    void detachCompare2Interrupt(void) { detachInterrupt(TIMER_CH2); } + +    /** @brief Deprecated; use detachInterrupt(TIMER_CH3) instead. */ +    void detachCompare3Interrupt(void) { detachInterrupt(TIMER_CH3); } + +    /** @brief Deprecated; use detachInterrupt(TIMER_CH4) instead. */ +    void detachCompare4Interrupt(void) { detachInterrupt(TIMER_CH4); } + +    /** @brief Deprecated; use refresh() instead. */ +    void generateUpdate(void) { refresh(); }  }; -/** Pre-instantiated timer for use by user code. */ +/* -- The rest of this file is deprecated. --------------------------------- */ + +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */  extern HardwareTimer Timer1; -/** Pre-instantiated timer for use by user code. */ +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */  extern HardwareTimer Timer2; -/** Pre-instantiated timer for use by user code. */ -extern HardwareTimer Timer3; -/** Pre-instantiated timer for use by user code. */ -extern HardwareTimer Timer4; -#if NR_TIMERS >= 8 -/** Pre-instantiated timer for use by user code, on devices with -    more than four timers (this does not include the Maple). */ -extern HardwareTimer Timer5; -/** Pre-instantiated timer for use by user code, on devices with -    more than four timers (this does not include the Maple). */ -extern HardwareTimer Timer8; -#endif -  /** - * Get one of the pre-instantiated HardwareTimer instances, given a - * timer device number. + * @brief Deprecated.   * - * Be careful not to pass an actual number to this function.  For - * example, getTimer(1) will not return Timer1.  Use a real - * timer_dev_num, e.g. TIMER1, TIMER2, etc. + * Pre-instantiated timer. + */ +extern HardwareTimer Timer3; +/** + * @brief Deprecated.   * - * @param timerNum the timer device number, e.g. TIMER1. + * Pre-instantiated timer. + */ +extern HardwareTimer Timer4; +#ifdef STM32_HIGH_DENSITY +/** + * @brief Deprecated.   * - * @return Pointer to the HardwareTimer instance corresponding to the - * given timer device number.  If timerNum is TIMER_INVALID, returns a - * null pointer. + * Pre-instantiated timer. + */ +extern HardwareTimer Timer5; +/** + * @brief Deprecated.   * - * @see timer_dev_num + * Pre-instantiated timer.   */ -HardwareTimer* getTimer(timer_dev_num timerNum); - +extern HardwareTimer Timer8;  #endif +#endif diff --git a/wirish/Print.cpp b/wirish/Print.cpp index 9c52321..9130c9c 100644 --- a/wirish/Print.cpp +++ b/wirish/Print.cpp @@ -1,127 +1,121 @@ -/****************************************************************************** - * The MIT License +/* + * Print.cpp - Base class that provides print() and println() + * Copyright (c) 2008 David A. Mellis.  All right reserved.   * - * Copyright (c) 2011 LeafLabs, LLC. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version.   * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.   * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA   * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ + * Modified 23 November 2006 by David A. Mellis + * Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com> + */  #include "Print.h" -#include <cstdio> -#include <climits> -#include <cstring> - -// We'll allocate character buffers of size INT_BUF_SIZE to hold the -// string representations of numbers; this value ensures that they're -// big enough to accomodate the biggest integral value + null byte. -// -// E.g., consider -(2^63-1) = -9223372036854775807, which is 20 -// characters long, including the minus sign.  The other edge cases -// are similar. -// -// (Nonetheless, use snprintf everywhere, just in case of error). -#define INT_BUF_SIZE 21 - -// An IEEE-754 double buys you about 16 digits of precision; there's -// the possibility of minus signs, a decimal point, 'e+'/'e-', etc. -// While the Right Thing is to follow Steele and White, I'm just going -// to double what I consider a safe number of bytes and hope for the -// best. -#define DOUBLE_BUF_SIZE 40 - -static void fillBase(char *buf, int buf_size, int64 n, -                     uint8 n_real_bits, int base); -static void fillBinary(char *buf, int64 n, int start_bit); -static char baseToFmtSpec(int base); +#include <limits.h> + +#ifndef LLONG_MAX +/* + * Note: + * + * At time of writing (12 April 2011), the limits.h that came with the + * newlib we distributed didn't include LLONG_MAX.  Because we're + * staying away from using templates (see /notes/coding_standard.rst, + * "Language Features and Compiler Extensions"), this value was + * copy-pasted from a println() of the value + * + *     std::numeric_limits<long long>::max(). + */ +#define LLONG_MAX 9223372036854775807LL +#endif + +#include "wirish_math.h" + +/* + * Public methods + */  void Print::write(const char *str) { -    for (const char *c = str; *c != '\0'; c++) { -        write(*c); +    while (*str) { +        write(*str++);      }  } -void Print::write(void *buffer, uint32 size) { -    for (uint32 i = 0; i < size; i++) { -        write(*((uint8*)buffer + i)); +void Print::write(const void *buffer, uint32 size) { +    uint8 *ch = (uint8*)buffer; +    while (size--) { +        write(*ch++);      }  } +void Print::print(uint8 b) { +    this->write(b); +} +  void Print::print(char c) { -    print((uint8) c); +    print((uint8)c);  }  void Print::print(const char str[]) {      write(str);  } -void Print::print(uint8 b) { -    write(b); +void Print::print(int n) { +    print((long long)n);  } -void Print::print(int32 n) { -    print(n, DEC); +void Print::print(unsigned int n) { +    print((unsigned long long)n);  } -void Print::print(uint32 n) { -    print((uint64) n); +void Print::print(long n) { +    print((long long)n);  } -void Print::print(int64 n) { -    print(n, DEC); +void Print::print(unsigned long n) { +    print((unsigned long long)n);  } -void Print::print(uint64 n) { -    char buf[INT_BUF_SIZE]; -    snprintf(buf, INT_BUF_SIZE, "%llu", n); -    write(buf); +void Print::print(long long n) { +    if (n < 0) { +        print('-'); +        n = -n; +    } +    printNumber(n, 10);  } -void Print::print(int32 n, int base) { -    // Worst case: sign bit set && base == BIN: 32 bytes for digits + -    // 1 null (base == BIN means no minus sign). -    char buf[33]; -    fillBase(buf, sizeof(buf), (int64)n, 32, base); -    write(buf); +void Print::print(unsigned long long n) { +    printNumber(n, 10);  } -void Print::print(int64 n, int base) { -    // As above, but now 64 bytes for bits + 1 null -    char buf[65]; -    fillBase(buf, sizeof(buf), n, 64, base); -    write(buf); +void Print::print(unsigned long long n, int base) { +    if (base == 0) { +        print((char)n); +    } else if (base == 10) { +        print(n); +    } else { +        printNumber(n, base); +    }  }  void Print::print(double n) { -    char buf[DOUBLE_BUF_SIZE]; -    // This breaks strict compliance with the Arduino library behavior -    // (which is equivalent to using "%.2f"), but that's really not -    // enough.  According to Stroustrup, "%f" without precision is -    // equivalent to ".6f", which is much better. -    snprintf(buf, DOUBLE_BUF_SIZE, "%f", n); -    write(buf); +    printFloat(n, 2);  }  void Print::println(void) { -    print("\r\n"); +    print('\r'); +    print('\n');  }  void Print::println(char c) { @@ -139,32 +133,37 @@ void Print::println(uint8 b) {      println();  } -void Print::println(int32 n) { +void Print::println(int n) {      print(n);      println();  } -void Print::println(uint32 n) { +void Print::println(unsigned int n) {      print(n);      println();  } -void Print::println(int64 n) { -    print(n); +void Print::println(long n) { +    print((long long)n); +    println(); +} + +void Print::println(unsigned long n) { +    print((unsigned long long)n);      println();  } -void Print::println(uint64 n) { +void Print::println(long long n) {      print(n);      println();  } -void Print::println(int32 n, int base) { -    print(n, base); +void Print::println(unsigned long long n) { +    print(n);      println();  } -void Print::println(int64 n, int base) { +void Print::println(unsigned long long n, int base) {      print(n, base);      println();  } @@ -174,54 +173,87 @@ void Print::println(double n) {      println();  } -// -- Auxiliary functions ----------------------------------------------------- +/* + * Private methods + */ -static void fillBase(char *buf, int buf_size, int64 n, -                     uint8 n_real_bits, int base) { -    if (base == BIN) { -        fillBinary(buf, n, n_real_bits - 1); -    } else { -        char spec = baseToFmtSpec(base); -        char fmt[5]; - -        if (base == BYTE) -            n = (uint8)n; - -        if (n_real_bits == 32) { -            snprintf(fmt, sizeof(fmt), "%%l%c", spec); -            snprintf(buf, buf_size, fmt, (int32)n); -        } else { -            snprintf(fmt, sizeof(fmt), "%%ll%c", spec); -            snprintf(buf, buf_size, fmt, n); -        } +void Print::printNumber(unsigned long long n, uint8 base) { +    unsigned char buf[CHAR_BIT * sizeof(long long)]; +    unsigned long i = 0; + +    if (n == 0) { +        print('0'); +        return; +    } + +    while (n > 0) { +        buf[i++] = n % base; +        n /= base; +    } + +    for (; i > 0; i--) { +        print((char)(buf[i - 1] < 10 ? +                     '0' + buf[i - 1] : +                     'A' + buf[i - 1] - 10));      }  } -// Assumes sizeof(buf) > start_bit. -static void fillBinary(char *buf, int64 n, int start_bit) { -    int b = 0;                // position in buf -    int i = start_bit;        // position in n's bits -    while(!(n & (1 << i))) { -        i--; +/* According to snprintf(), + * + * nextafter((double)numeric_limits<long long>::max(), 0.0) ~= 9.22337e+18 + * + * This slightly smaller value was picked semi-arbitrarily. */ +#define LARGE_DOUBLE_TRESHOLD (9.1e18) + +/* THIS FUNCTION SHOULDN'T BE USED IF YOU NEED ACCURATE RESULTS. + * + * This implementation is meant to be simple and not occupy too much + * code size.  However, printing floating point values accurately is a + * subtle task, best left to a well-tested library function. + * + * See Steele and White 2003 for more details: + * + * http://kurtstephens.com/files/p372-steele.pdf + */ +void Print::printFloat(double number, uint8 digits) { +    // Hackish fail-fast behavior for large-magnitude doubles +    if (abs(number) >= LARGE_DOUBLE_TRESHOLD) { +        if (number < 0.0) { +            print('-'); +        } +        print("<large double>"); +        return;      } -    for(; i >= 0; i--) { -        buf[b++] = '0' + ((n >> i) & 0x1); + +    // Handle negative numbers +    if (number < 0.0) { +        print('-'); +        number = -number; +    } + +    // Simplistic rounding strategy so that e.g. print(1.999, 2) +    // prints as "2.00" +    double rounding = 0.5; +    for (uint8 i = 0; i < digits; i++) { +        rounding /= 10.0;      } -    buf[b] = '\0'; -} - -static char baseToFmtSpec(int base) { -    switch (base) { -    case DEC: -        return 'd'; -    case HEX: -        return 'x'; -    case OCT: -        return 'o'; -    case BYTE: -        return 'd'; -    default: -        // Shouldn't happen, but give a sensible default -        return 'd'; +    number += rounding; + +    // Extract the integer part of the number and print it +    long long int_part = (long long)number; +    double remainder = number - int_part; +    print(int_part); + +    // Print the decimal point, but only if there are digits beyond +    if (digits > 0) { +        print("."); +    } + +    // Extract digits from the remainder one at a time +    while (digits-- > 0) { +        remainder *= 10.0; +        int to_print = (int)remainder; +        print(to_print); +        remainder -= to_print;      }  } diff --git a/wirish/Print.h b/wirish/Print.h index 4527948..73d82e7 100644 --- a/wirish/Print.h +++ b/wirish/Print.h @@ -1,68 +1,69 @@ -/****************************************************************************** - * The MIT License +/* + * Print.h - Base class that provides print() and println() + * Copyright (c) 2008 David A. Mellis.  All right reserved.   * - * Copyright (c) 2011 LeafLabs, LLC. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version.   * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.   * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA.   * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ + * Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com> + */  #ifndef _PRINT_H_  #define _PRINT_H_  #include "libmaple_types.h" -#define DEC   10 -#define HEX   16 -#define OCT    8 -#define BIN    2 -#define BYTE   0                // yuck +enum { +    BYTE = 0, +    BIN  = 2, +    OCT  = 8, +    DEC  = 10, +    HEX  = 16 +};  class Print { - public: -    virtual void write(uint8) = 0; +public: +    virtual void write(uint8 ch) = 0;      virtual void write(const char *str); -    virtual void write(void *buf, uint32 size); - +    virtual void write(const void *buf, uint32 len);      void print(char);      void print(const char[]);      void print(uint8); -    void print(int32); -    void print(uint32); -    void print(int64); -    void print(uint64); -    void print(int32, int); -    void print(int64, int); +    void print(int); +    void print(unsigned int); +    void print(long); +    void print(unsigned long); +    void print(long long); +    void print(unsigned long long); +    void print(unsigned long long, int);      void print(double); -      void println(void);      void println(char);      void println(const char[]);      void println(uint8); -    void println(int32); -    void println(uint32); -    void println(int64); -    void println(uint64); -    void println(int32, int); -    void println(int64, int); +    void println(int); +    void println(unsigned int); +    void println(long); +    void println(unsigned long); +    void println(long long); +    void println(unsigned long long); +    void println(unsigned long long, int);      void println(double); +private: +    void printNumber(unsigned long long, uint8); +    void printFloat(double, uint8);  };  #endif diff --git a/wirish/boards.cpp b/wirish/boards.cpp new file mode 100644 index 0000000..9e25eeb --- /dev/null +++ b/wirish/boards.cpp @@ -0,0 +1,160 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + *****************************************************************************/ + +/** + * @brief Generic board initialization routines. + * + * By default, we bring up all Maple boards to 72MHz, clocked off the + * PLL, driven by the 8MHz external crystal. AHB and APB2 are clocked + * at 72MHz.  APB1 is clocked at 36MHz. + */ + +#include "boards.h" + +#include "flash.h" +#include "rcc.h" +#include "nvic.h" +#include "systick.h" +#include "gpio.h" +#include "adc.h" +#include "timer.h" +#include "usb.h" + +static void setupFlash(void); +static void setupClocks(void); +static void setupNVIC(void); +static void setupADC(void); +static void setupTimers(void); + +void init(void) { +    setupFlash(); +    setupClocks(); +    setupNVIC(); +    systick_init(SYSTICK_RELOAD_VAL); +    gpio_init_all(); +    afio_init(); +    setupADC(); +    setupTimers(); +    setupUSB(); +    boardInit(); +} + +/* You could farm this out to the files in boards/ if e.g. it takes + * too long to test on Maple Native (all those FSMC pins...). */ +bool boardUsesPin(uint8 pin) { +    for (int i = 0; i < BOARD_NR_USED_PINS; i++) { +        if (pin == boardUsedPins[i]) { +            return true; +        } +    } +    return false; +} + +static void setupFlash(void) { +    flash_enable_prefetch(); +    flash_set_latency(FLASH_WAIT_STATE_2); +} + +/* + * Clock setup.  Note that some of this only takes effect if we're + * running bare metal and the bootloader hasn't done it for us + * already. + * + * If you change this function, you MUST change the file-level Doxygen + * comment above. + */ +static void setupClocks() { +    rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9); +    rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); +    rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2); +    rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); +} + +static void setupNVIC() { +#ifdef VECT_TAB_FLASH +    nvic_init(USER_ADDR_ROM, 0); +#elif defined VECT_TAB_RAM +    nvic_init(USER_ADDR_RAM, 0); +#elif defined VECT_TAB_BASE +    nvic_init((uint32)0x08000000, 0); +#else +#error "You must select a base address for the vector table." +#endif +} + +static void adcDefaultConfig(const adc_dev* dev); + +static void setupADC() { +    adc_foreach(adcDefaultConfig); +} + +static void timerDefaultConfig(timer_dev*); + +static void setupTimers() { +    timer_foreach(timerDefaultConfig); +} + +static void adcDefaultConfig(const adc_dev *dev) { +    adc_init(dev); + +    adc_set_extsel(dev, ADC_SWSTART); +    adc_set_exttrig(dev, true); + +    adc_enable(dev); +    adc_calibrate(dev); +    adc_set_sample_rate(dev, ADC_SMPR_55_5); +} + +static void timerDefaultConfig(timer_dev *dev) { +    timer_adv_reg_map *regs = (dev->regs).adv; +    const uint16 full_overflow = 0xFFFF; +    const uint16 half_duty = 0x8FFF; + +    timer_init(dev); +    timer_pause(dev); + +    regs->CR1 = TIMER_CR1_ARPE; +    regs->PSC = 1; +    regs->SR = 0; +    regs->DIER = 0; +    regs->EGR = TIMER_EGR_UG; + +    switch (dev->type) { +    case TIMER_ADVANCED: +        regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF; +        // fall-through +    case TIMER_GENERAL: +        timer_set_reload(dev, full_overflow); + +        for (int channel = 1; channel <= 4; channel++) { +            timer_set_compare(dev, channel, half_duty); +            timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); +        } +        // fall-through +    case TIMER_BASIC: +        break; +    } + +    timer_resume(dev); +} diff --git a/wirish/boards.h b/wirish/boards.h index f8505ab..2515c00 100644 --- a/wirish/boards.h +++ b/wirish/boards.h @@ -3,29 +3,37 @@   *   * Copyright (c) 2010 Bryan Newbold.   * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is   * furnished to do so, subject to the following conditions:   * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software.   * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE.   *****************************************************************************/ -/* This file contains board-specific pin mapping tables. To add a new board - * type, copy the "BOARD_maple" section below and edit it as needed, then - * update your build toolchain with a new "BOARD" type. This must match the - * separate MCU type (which determines the ../libmaple configuration). +/** + * @file boards.h + * @author Bryan Newbold <bnewbold@leaflabs.com>, + *         Marti Bolivar <mbolivar@leaflabs.com> + * @brief Board-specific pin information. + * + * To add a new board type, add a new pair of files to + * /wirish/boards/, update the section below with a new "BOARD" type, + * and update /wirish/rules.mk to include your boards/your_board.cpp + * file in the top-level Makefile build.   */  #ifndef _BOARDS_H_ @@ -33,14 +41,14 @@  #include "libmaple.h"  #include "gpio.h" -#include "timers.h" -#include "exti.h" +#include "timer.h" -#ifdef __cplusplus -extern "C" { -#endif +#include "wirish_types.h" -/* Set of all possible digital pin names; not all boards have all these */ +/* Set of all possible pin names; not all boards have all these (note + * that we use the Dx convention since all of the Maple's pins are + * "digital" pins (e.g. can be used with digitalRead() and + * digitalWrite()), but not all of them are connected to ADCs. */  enum {      D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16,      D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, @@ -51,444 +59,97 @@ enum {      D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105,      D106, D107, D108, D109, D110, D111, }; -/* Set of all possible analog pin names; not all boards have all these */ -enum { -    ADC0, ADC1, ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, ADC10, ADC11, -    ADC12, ADC13, ADC14, ADC15, ADC16, ADC17, ADC18, ADC19, ADC20, }; - -#define ADC_INVALID       0xFFFFFFFF - -/* Types used for the tables below */ -typedef struct PinMapping { -    GPIO_Port *port; -    uint32 pin; -    uint32 adc; -    TimerCCR timer_ccr; -    uint32 exti_port; -    timer_dev_num timer_num; -    uint32 timer_chan; -} PinMapping; - -/* LeafLabs Maple rev3, rev5 */ -#ifdef BOARD_maple +/** + * @brief Maps each Maple pin to a corresponding stm32_pin_info. + * @see stm32_pin_info + */ +extern const stm32_pin_info PIN_MAP[]; -    #define CYCLES_PER_MICROSECOND  72 -    #define SYSTICK_RELOAD_VAL      71999 /* takes a cycle to reload */ +/** + * @brief Pins capable of PWM output. + * + * Its length is BOARD_NR_PWM_PINS. + */ +extern const uint8 boardPWMPins[]; -    #define BOARD_BUTTON_PIN   38 -    #define BOARD_LED_PIN      13 +/** + * @brief Array of pins capable of analog input. + * + * Its length is BOARD_NR_ADC_PINS. + */ +extern const uint8 boardADCPins[]; -    static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = { -        /* D0/PA3 */ -        {GPIOA_BASE,  3,        ADC3, TIMER2_CH4_CCR,  EXTI_CONFIG_PORTA, TIMER2, 4}, -        /* D1/PA2 */ -        {GPIOA_BASE,  2,        ADC2, TIMER2_CH3_CCR,  EXTI_CONFIG_PORTA, TIMER2, 3}, -        /* D2/PA0 */ -        {GPIOA_BASE,  0,        ADC0, TIMER2_CH1_CCR,  EXTI_CONFIG_PORTA, TIMER2, 1}, -        /* D3/PA1 */ -        {GPIOA_BASE,  1,        ADC1, TIMER2_CH2_CCR,  EXTI_CONFIG_PORTA, TIMER2, 2}, -        /* D4/PB5 */ -        {GPIOB_BASE,  5, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D5/PB6 */ -        {GPIOB_BASE,  6, ADC_INVALID, TIMER4_CH1_CCR,  EXTI_CONFIG_PORTB, TIMER4, 1}, -        /* D6/PA8 */ -        {GPIOA_BASE,  8, ADC_INVALID, TIMER1_CH1_CCR,  EXTI_CONFIG_PORTA, TIMER1, 1}, -        /* D7/PA9 */ -        {GPIOA_BASE,  9, ADC_INVALID, TIMER1_CH2_CCR,  EXTI_CONFIG_PORTA, TIMER1, 2}, -        /* D8/PA10 */ -        {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR,  EXTI_CONFIG_PORTA, TIMER1, 3}, -        /* D9/PB7 */ -        {GPIOB_BASE,  7, ADC_INVALID, TIMER4_CH2_CCR,  EXTI_CONFIG_PORTB, TIMER4, 2}, -        /* D10/PA4 */ -        {GPIOA_BASE,  4,        ADC4,              0,  EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D11/PA7 */ -        {GPIOA_BASE,  7,        ADC7, TIMER3_CH2_CCR,  EXTI_CONFIG_PORTA, TIMER3, 2}, -        /* D12/PA6 */ -        {GPIOA_BASE,  6,        ADC6, TIMER3_CH1_CCR,  EXTI_CONFIG_PORTA, TIMER3, 1}, -        /* D13/PA5 */ -        {GPIOA_BASE,  5,        ADC5,              0,  EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D14/PB8 */ -        {GPIOB_BASE,  8, ADC_INVALID, TIMER4_CH3_CCR,  EXTI_CONFIG_PORTB, TIMER4, 3}, +/** + * @brief Pins which are connected to external hardware. + * + * For example, on Maple boards, it always at least includes + * BOARD_LED_PIN.  Its length is BOARD_NR_USED_PINS. + */ +extern const uint8 boardUsedPins[]; -        /* Little header */ +/** + * @brief Generic board initialization function. + * + * This function is called before main().  It ensures that the clocks + * and peripherals are configured properly for use with wirish, then + * calls boardInit(). + * + * @see boardInit() + */ +void init(void); -        /* D15/PC0 */ -        {GPIOC_BASE,  0,       ADC10,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D16/PC1 */ -        {GPIOC_BASE,  1,       ADC11,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D17/PC2 */ -        {GPIOC_BASE,  2,       ADC12,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D18/PC3 */ -        {GPIOC_BASE,  3,       ADC13,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D19/PC4 */ -        {GPIOC_BASE,  4,       ADC14,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D20/PC5 */ -        {GPIOC_BASE,  5,       ADC15,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, +/** + * @brief Board-specific initialization function. + * + * This function is called from init() after all generic board + * initialization has been performed.  Each board is required to + * define its own. + * + * @see init() + */ +extern void boardInit(void); -        /* External header */ +/** + * @brief Test if a pin is used for a special purpose on your board. + * @param pin Pin to test + * @return true if the given pin is in boardUsedPins, and false otherwise. + * @see boardUsedPins + */ +bool boardUsesPin(uint8 pin); -        /* D21/PC13 */ -        {GPIOC_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D22/PC14 */ -        {GPIOC_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D23/PC15 */ -        {GPIOC_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D24/PB9 */ -        {GPIOB_BASE,  9, ADC_INVALID, TIMER4_CH4_CCR,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D25/PD2 */ -        {GPIOD_BASE,  2, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D26/PC10 */ -        {GPIOC_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D27/PB0 */ -        {GPIOB_BASE,  0,        ADC8, TIMER3_CH3_CCR,  EXTI_CONFIG_PORTB, TIMER3, 3}, -        /* D28/PB1 */ -        {GPIOB_BASE,  1,        ADC9, TIMER3_CH4_CCR,  EXTI_CONFIG_PORTB, TIMER3, 4}, -        /* D29/PB10 */ -        {GPIOB_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D30/PB11 */ -        {GPIOB_BASE, 11, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D31/PB12 */ -        {GPIOB_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D32/PB13 */ -        {GPIOB_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D33/PB14 */ -        {GPIOB_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D34/PB15 */ -        {GPIOB_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D35/PC6 */ -        {GPIOC_BASE,  6, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D36/PC7 */ -        {GPIOC_BASE,  7, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D37/PC8 */ -        {GPIOC_BASE,  8, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D38/PC9 (BUT) */ -        {GPIOC_BASE,  9, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID} -    }; +/* Include the appropriate private header from boards/: */ -    #define BOARD_INIT do {                           \ -        } while(0) +/* FIXME HACK put boards/ before these paths once IDE uses make. */ +#ifdef BOARD_maple +#include "maple.h"  #elif defined(BOARD_maple_native) - -    /* LeafLabs Maple Native (prototype) */ - -    #define CYCLES_PER_MICROSECOND  72 -    #define SYSTICK_RELOAD_VAL      71999 /* takes a cycle to reload */ - -    #define BOARD_LED_PIN           D21 -    #define BOARD_BUTTON_PIN        D18 - -    static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = { -        /* Top header */ - -        /* D0/PB10 */ -        {GPIOB_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D1/PB2 */ -        {GPIOB_BASE,  2, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D2/PB12 */ -        {GPIOB_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D3/PB13 */ -        {GPIOB_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D4/PB14 */ -        {GPIOB_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D5/PB15 */ -        {GPIOB_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D6/PC0 */ -        {GPIOC_BASE,  0,       ADC10,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D7/PC1 */ -        {GPIOC_BASE,  1,       ADC11,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D8/PC2 */ -        {GPIOC_BASE,  2,       ADC12,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D9/PC3 */ -        {GPIOC_BASE,  3,       ADC13,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D10/PC4 */ -        {GPIOC_BASE,  4,       ADC14,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D11/PC5 */ -        {GPIOC_BASE,  5,       ADC15,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D12/PC6 */ -        {GPIOC_BASE,  6, ADC_INVALID, TIMER8_CH1_CCR,  EXTI_CONFIG_PORTC,        TIMER8, 1}, -        /* D13/PC7 */ -        {GPIOC_BASE,  7, ADC_INVALID, TIMER8_CH2_CCR,  EXTI_CONFIG_PORTC,        TIMER8, 2}, -        /* D14/PC8 */ -        {GPIOC_BASE,  8, ADC_INVALID, TIMER8_CH3_CCR,  EXTI_CONFIG_PORTC,        TIMER8, 3}, -        /* D15/PC9 */ -        {GPIOC_BASE,  9, ADC_INVALID, TIMER8_CH4_CCR,  EXTI_CONFIG_PORTC,        TIMER8, 4}, -        /* D16/PC10 */ -        {GPIOC_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D17/PC11 */ -        {GPIOC_BASE, 11, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D18/PC12 */ -        {GPIOC_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D19/PC13 */ -        {GPIOC_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D20/PC14 */ -        {GPIOC_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D21/PC15 */ -        {GPIOC_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D22/PA8 */ -        {GPIOA_BASE,  8, ADC_INVALID, TIMER1_CH1_CCR,  EXTI_CONFIG_PORTA,        TIMER1, 1}, -        /* D23/PA9 */ -        {GPIOA_BASE,  9, ADC_INVALID, TIMER1_CH2_CCR,  EXTI_CONFIG_PORTA,        TIMER1, 2}, -        /* D24/PA10 */ -        {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR,  EXTI_CONFIG_PORTA,        TIMER1, 3}, -        /* D25/PB9 */ -        {GPIOB_BASE,  9, ADC_INVALID, TIMER4_CH4_CCR,  EXTI_CONFIG_PORTB,        TIMER4, 4}, - -        /* Bottom header */ - -        /* D26/PD2 */ -        {GPIOD_BASE,  2, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D27/PD3 */ -        {GPIOD_BASE,  3, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D28/PD6 */ -        {GPIOD_BASE,  6, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D29/PG11 */ -        {GPIOG_BASE, 11, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D30/PG12 */ -        {GPIOG_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D31/PG13 */ -        {GPIOG_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D32/PG14 */ -        {GPIOG_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D33/PG8 */ -        {GPIOG_BASE,  8, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D34/PG7 */ -        {GPIOG_BASE,  7, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D35/PG6 */ -        {GPIOG_BASE,  6, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D36/PB5 */ -        {GPIOB_BASE,  5, ADC_INVALID,              0,  EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D37/PB6 */ -        {GPIOB_BASE,  6, ADC_INVALID, TIMER4_CH1_CCR,  EXTI_CONFIG_PORTB,        TIMER4, 1}, -        /* D38/PB7 */ -        {GPIOB_BASE,  7, ADC_INVALID, TIMER4_CH2_CCR,  EXTI_CONFIG_PORTB,        TIMER4, 2}, -        /* D39/PF6 */ -        {GPIOF_BASE,  6,        ADC4,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D40/PF7 */ -        {GPIOF_BASE,  7,        ADC5,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D41/PF8 */ -        {GPIOF_BASE,  8,        ADC6,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D42/PF9 */ -        {GPIOF_BASE,  9,        ADC7,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D43/PF10 */ -        {GPIOF_BASE, 10,        ADC8,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D44/PF11 */ -        {GPIOF_BASE, 11, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D45/PB1 */ -        {GPIOB_BASE,  1,        ADC9, TIMER3_CH4_CCR,  EXTI_CONFIG_PORTB,        TIMER3, 4}, -        /* D46/PB0 */ -        {GPIOB_BASE,  0,        ADC8, TIMER3_CH3_CCR,  EXTI_CONFIG_PORTB,        TIMER3, 3}, -        /* D47/PA0 */ -        {GPIOA_BASE,  0,        ADC0, TIMER5_CH1_CCR,  EXTI_CONFIG_PORTA,        TIMER5, 1}, -        /* D48/PA1 */ -        {GPIOA_BASE,  1,        ADC1, TIMER5_CH2_CCR,  EXTI_CONFIG_PORTA,        TIMER5, 2}, /* FIXME (?) what to do about D48--D50 -                                                                                                also being TIMER2_CH[2,3,4]? */ -        /* D49/PA2 */ -        {GPIOA_BASE,  2,        ADC2, TIMER5_CH3_CCR,  EXTI_CONFIG_PORTA,        TIMER5, 3}, -        /* D50/PA3 */ -        {GPIOA_BASE,  3,        ADC3, TIMER5_CH4_CCR,  EXTI_CONFIG_PORTA,        TIMER5, 4}, -        /* D51/PA4 */ -        {GPIOA_BASE,  4,        ADC4,              0,  EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D52/PA5 */ -        {GPIOA_BASE,  5,        ADC5,              0,  EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D53/PA6 */ -        {GPIOA_BASE,  6,        ADC6, TIMER3_CH1_CCR,  EXTI_CONFIG_PORTA,        TIMER3, 1}, -        /* D54/PA7 */ -        {GPIOA_BASE,  7,        ADC7, TIMER3_CH2_CCR,  EXTI_CONFIG_PORTA,        TIMER3, 2}, - -        /* Right (triple) header */ - -        /* D55/PF0 */ -        {GPIOF_BASE,  0, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D56/PD11 */ -        {GPIOD_BASE, 11, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D57/PD14 */ -        {GPIOD_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D58/PF1 */ -        {GPIOF_BASE,  1, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D59/PD12 */ -        {GPIOD_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D60/PD15 */ -        {GPIOD_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D61/PF2 */ -        {GPIOF_BASE,  2, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D62/PD13 */ -        {GPIOD_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D63/PD0 */ -        {GPIOD_BASE,  0, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D64/PF3 */ -        {GPIOF_BASE,  3, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D65/PE3 */ -        {GPIOE_BASE,  3, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D66/PD1 */ -        {GPIOD_BASE,  1, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D67/PF4 */ -        {GPIOF_BASE,  4, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D68/PE4 */ -        {GPIOE_BASE,  4, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D69/PE7 */ -        {GPIOE_BASE,  7, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D70/PF5 */ -        {GPIOF_BASE,  5, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D71/PE5 */ -        {GPIOE_BASE,  5, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D72/PE8 */ -        {GPIOE_BASE,  8, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D73/PF12 */ -        {GPIOF_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D74/PE6 */ -        {GPIOE_BASE,  6, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D75/PE9 */ -        {GPIOE_BASE,  9, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D76/PF13 */ -        {GPIOF_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D77/PE10 */ -        {GPIOE_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D78/PF14 */ -        {GPIOF_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D79/PG9 */ -        {GPIOG_BASE,  9, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D80/PE11 */ -        {GPIOE_BASE, 11, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D81/PF15 */ -        {GPIOF_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID}, -        /* D82/PG10 */ -        {GPIOG_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D83/PE12 */ -        {GPIOE_BASE, 12, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D84/PG0 */ -        {GPIOG_BASE,  0, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D85/PD5 */ -        {GPIOD_BASE,  5, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D86/PE13 */ -        {GPIOE_BASE, 13, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D87/PG1 */ -        {GPIOG_BASE,  1, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D88/PD4 */ -        {GPIOD_BASE,  4, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D89/PE14 */ -        {GPIOE_BASE, 14, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D90/PG2 */ -        {GPIOG_BASE,  2, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D91/PE1 */ -        {GPIOE_BASE,  1, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D92/PE15 */ -        {GPIOE_BASE, 15, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D93/PG3 */ -        {GPIOG_BASE,  3, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D94/PE0 */ -        {GPIOE_BASE,  0, ADC_INVALID,              0,  EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID}, -        /* D95/PD8 */ -        {GPIOD_BASE,  8, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D96/PG4 */ -        {GPIOG_BASE,  4, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D97/PD9 */ -        {GPIOD_BASE,  9, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}, -        /* D98/PG5 */ -        {GPIOG_BASE,  5, ADC_INVALID,              0,  EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID}, -        /* D99/PD10 */ -        {GPIOD_BASE, 10, ADC_INVALID,              0,  EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID} -    }; - -    #define BOARD_INIT do {                           \ -        } while(0) - +#include "maple_native.h"  #elif defined(BOARD_maple_mini) - -    #define CYCLES_PER_MICROSECOND 72 -    #define SYSTICK_RELOAD_VAL     71999 /* takes a cycle to reload */ - -    #define BOARD_BUTTON_PIN 32 -    #define BOARD_LED_PIN    33 - -    static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = { -        /* D0/PB11 */ -        {GPIOB_BASE, 11,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D1/PB10 */ -        {GPIOB_BASE, 10,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D2/PB2 */ -        {GPIOB_BASE,  2,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D3/PB0 */ -        {GPIOB_BASE,  0,  ADC8,        TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3,        3}, -        /* D4/PA7 */ -        {GPIOA_BASE,  7,  ADC7,        TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3,        2}, -        /* D5/PA6 */ -        {GPIOA_BASE,  6,  ADC6,        TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3,        1}, -        /* D6/PA5 */ -        {GPIOA_BASE,  5,  ADC5,                    0,  EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D7/PA4 */ -        {GPIOA_BASE,  4,  ADC4,                    0,  EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D8/PA3 */ -        {GPIOA_BASE,  3,  ADC3,        TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2,        4}, -        /* D9/PA2 */ -        {GPIOA_BASE,  2,  ADC2,        TIMER2_CH3_CCR, EXTI_CONFIG_PORTA, TIMER2,        3}, -        /* D10/PA1 */ -        {GPIOA_BASE,  1,  ADC1,        TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2,        2}, -        /* D11/PA0 */ -        {GPIOA_BASE,  0,  ADC0,        TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2,        1}, -        /* D12/PC15 */ -        {GPIOC_BASE, 15,  ADC_INVALID,              0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D13/PC14 */ -        {GPIOC_BASE, 14,  ADC_INVALID,              0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D14/PC13 */ -        {GPIOC_BASE, 13,  ADC_INVALID,              0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, -        /* D15/PB7 */ -        {GPIOB_BASE,  7,  ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4,        1}, -        /* D16/PB6 */ -        {GPIOB_BASE,  6,  ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4,        1}, -        /* D17/PB5 */ -        {GPIOB_BASE,  5,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D18/PB4 */ -        {GPIOB_BASE,  4,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D19/PB3 */ -        {GPIOB_BASE,  3,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D20/PA15 */ -        {GPIOA_BASE, 15,  ADC_INVALID,              0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D21/PA14 */ -        {GPIOA_BASE, 14,  ADC_INVALID,              0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D22/PA13 */ -        {GPIOA_BASE, 13,  ADC_INVALID,              0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D23/PA12 */ -        {GPIOA_BASE, 12,  ADC_INVALID,              0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID}, -        /* D24/PA11 */ -        {GPIOA_BASE, 11,  ADC_INVALID, TIMER1_CH4_CCR, EXTI_CONFIG_PORTA, TIMER1,        4}, -        /* D25/PA10 */ -        {GPIOA_BASE, 10,  ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA, TIMER1,        3}, -        /* D26/PA9 */ -        {GPIOA_BASE,  9,  ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2,        2}, -        /* D27/PA8 */ -        {GPIOA_BASE,  8,  ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTB, TIMER1,        1}, -        /* D28/PB15 */ -        {GPIOB_BASE, 15,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D29/PB14 */ -        {GPIOB_BASE, 14,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D30/PB13 */ -        {GPIOB_BASE, 13,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D31/PB12 */ -        {GPIOB_BASE, 12,  ADC_INVALID,              0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, -        /* D32/PB8 */ -        {GPIOB_BASE,  8,  ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4,        3}, -        /* D33/PB1 */ -        {GPIOB_BASE,  1,  ADC9,        TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3,        4}, -    }; - -    /* since we want the Serial Wire/JTAG pins as GPIOs, disable both -       SW and JTAG debug support */ -    /* don't use __clear_bits here! */ -    #define BOARD_INIT                                                  \ -        do {                                                            \ -            *AFIO_MAPR = (*AFIO_MAPR | BIT(26)) & ~(BIT(25) | BIT(24)); \ -        } while (0) - +#include "maple_mini.h" +#elif defined(BOARD_maple_RET6) +/* + * **NOT** MAPLE REV6.  This the **Maple RET6 EDITION**, which is a + * Maple with an STM32F103RET6 (...RET6) instead of an STM32F103RBT6 + * (...RBT6) on it.  Maple Rev6 (as of March 2011) DOES NOT EXIST. + */ +#include "maple_RET6.h"  #else - +/* + * TODO turn this into a warning so people can: + * + * #include "my_board_config.h" + * #include "wirish.h" + * + * This will enable third-party board support without requiring that + * anybody hack around in libmaple itself. + */  #error "Board type has not been selected correctly." -  #endif -#ifdef __cplusplus -} // extern "C" -#endif +/* Set derived definitions */ -#endif +#define CLOCK_SPEED_MHZ                 CYCLES_PER_MICROSECOND +#define CLOCK_SPEED_HZ                  (CLOCK_SPEED_MHZ * 1000000UL) +#endif diff --git a/wirish/boards/maple.cpp b/wirish/boards/maple.cpp new file mode 100644 index 0000000..2d35e7b --- /dev/null +++ b/wirish/boards/maple.cpp @@ -0,0 +1,115 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple.cpp + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Maple PIN_MAP and boardInit(). + */ + +#include "gpio.h" +#include "timer.h" + +#include "maple.h" + +#ifdef BOARD_maple + +void boardInit(void) { +} + +extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { + +    /* Top header */ + +    {GPIOA, TIMER2, ADC1,  3, 4,    3}, /* D0/PA3 */ +    {GPIOA, TIMER2, ADC1,  2, 3,    2}, /* D1/PA2 */ +    {GPIOA, TIMER2, ADC1,  0, 1,    0}, /* D2/PA0 */ +    {GPIOA, TIMER2, ADC1,  1, 2,    1}, /* D3/PA1 */ +    {GPIOB,   NULL, NULL,  5, 0, ADCx}, /* D4/PB5 */ +    {GPIOB, TIMER4, NULL,  6, 1, ADCx}, /* D5/PB6 */ +    {GPIOA, TIMER1, NULL,  8, 1, ADCx}, /* D6/PA8 */ +    {GPIOA, TIMER1, NULL,  9, 2, ADCx}, /* D7/PA9 */ +    {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D8/PA10 */ +    {GPIOB, TIMER4, NULL,  7, 2, ADCx}, /* D9/PB7 */ +    {GPIOA,   NULL, ADC1,  4, 0,    4}, /* D10/PA4 */ +    {GPIOA, TIMER3, ADC1,  7, 2,    7}, /* D11/PA7 */ +    {GPIOA, TIMER3, ADC1,  6, 1,    6}, /* D12/PA6 */ +    {GPIOA,   NULL, ADC1,  5, 0,    5}, /* D13/PA5 (LED) */ +    {GPIOB, TIMER4, NULL,  8, 3, ADCx}, /* D14/PB8 */ + +    /* Little header */ + +    {GPIOC,   NULL, ADC1,  0, 0,   10}, /* D15/PC0 */ +    {GPIOC,   NULL, ADC1,  1, 0,   11}, /* D16/PC1 */ +    {GPIOC,   NULL, ADC1,  2, 0,   12}, /* D17/PC2 */ +    {GPIOC,   NULL, ADC1,  3, 0,   13}, /* D18/PC3 */ +    {GPIOC,   NULL, ADC1,  4, 0,   14}, /* D19/PC4 */ +    {GPIOC,   NULL, ADC1,  5, 0,   15}, /* D20/PC5 */ + +    /* External header */ + +    {GPIOC,   NULL, NULL, 13, 0, ADCx}, /* D21/PC13 */ +    {GPIOC,   NULL, NULL, 14, 0, ADCx}, /* D22/PC14 */ +    {GPIOC,   NULL, NULL, 15, 0, ADCx}, /* D23/PC15 */ +    {GPIOB, TIMER4, NULL,  9, 4, ADCx}, /* D24/PB9 */ +    {GPIOD,   NULL, NULL,  2, 0, ADCx}, /* D25/PD2 */ +    {GPIOC,   NULL, NULL, 10, 0, ADCx}, /* D26/PC10 */ +    {GPIOB, TIMER3, ADC1,  0, 3,    8}, /* D27/PB0 */ +    {GPIOB, TIMER3, ADC1,  1, 4,    9}, /* D28/PB1 */ +    {GPIOB,   NULL, NULL, 10, 0, ADCx}, /* D29/PB10 */ +    {GPIOB,   NULL, NULL, 11, 0, ADCx}, /* D30/PB11 */ +    {GPIOB,   NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */ +    {GPIOB,   NULL, NULL, 13, 0, ADCx}, /* D32/PB13 */ +    {GPIOB,   NULL, NULL, 14, 0, ADCx}, /* D33/PB14 */ +    {GPIOB,   NULL, NULL, 15, 0, ADCx}, /* D34/PB15 */ +    {GPIOC,   NULL, NULL,  6, 0, ADCx}, /* D35/PC6 */ +    {GPIOC,   NULL, NULL,  7, 0, ADCx}, /* D36/PC7 */ +    {GPIOC,   NULL, NULL,  8, 0, ADCx}, /* D37/PC8 */ +    {GPIOC,   NULL, NULL,  9, 0, ADCx}, /* D38/PC9 (BUT) */ + +    /* JTAG header */ + +    {GPIOA,   NULL, NULL, 13, 0, ADCx}, /* D39/PA13 */ +    {GPIOA,   NULL, NULL, 14, 0, ADCx}, /* D40/PA14 */ +    {GPIOA,   NULL, NULL, 15, 0, ADCx}, /* D41/PA15 */ +    {GPIOB,   NULL, NULL,  3, 0, ADCx}, /* D42/PB3  */ +    {GPIOB,   NULL, NULL,  4, 0, ADCx}, /* D43/PB4  */ +}; + +extern const uint8 boardPWMPins[] __FLASH__ = { +    0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 24, 25, 27, 28 +}; + +extern const uint8 boardADCPins[] __FLASH__ = { +    0, 1, 2, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 27, 28 +}; + +extern const uint8 boardUsedPins[] __FLASH__ = { +    BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN, +    BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN +}; + +#endif diff --git a/wirish/boards/maple.h b/wirish/boards/maple.h new file mode 100644 index 0000000..4b55f7a --- /dev/null +++ b/wirish/boards/maple.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple.h + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Private include file for Maple in boards.h + */ + +#include "wirish_types.h" + +#ifndef _BOARD_MAPLE_H_ +#define _BOARD_MAPLE_H_ + +#define CYCLES_PER_MICROSECOND  72 +#define SYSTICK_RELOAD_VAL      71999 /* takes a cycle to reload */ + +#define BOARD_BUTTON_PIN        38 +#define BOARD_LED_PIN           13 + +/* Number of USARTs/UARTs whose pins are broken out to headers */ +#define BOARD_NR_USARTS         3 + +/* Default USART pin numbers (not considering AFIO remap) */ +#define BOARD_USART1_TX_PIN     7 +#define BOARD_USART1_RX_PIN     8 +#define BOARD_USART2_TX_PIN     1 +#define BOARD_USART2_RX_PIN     0 +#define BOARD_USART3_TX_PIN     29 +#define BOARD_USART3_RX_PIN     30 + +/* Number of SPI ports */ +#define BOARD_NR_SPI            2 + +/* Default SPI pin numbers (not considering AFIO remap) */ +#define BOARD_SPI1_NSS_PIN      10 +#define BOARD_SPI1_MOSI_PIN     11 +#define BOARD_SPI1_MISO_PIN     12 +#define BOARD_SPI1_SCK_PIN      13 +#define BOARD_SPI2_NSS_PIN      31 +#define BOARD_SPI2_MOSI_PIN     34 +#define BOARD_SPI2_MISO_PIN     33 +#define BOARD_SPI2_SCK_PIN      32 + +/* Total number of GPIO pins that are broken out to headers and + * intended for general use. */ +#define BOARD_NR_GPIO_PINS      44 + +/* Number of pins capable of PWM output */ +#define BOARD_NR_PWM_PINS       16 + +/* Number of pins capable of ADC conversion */ +#define BOARD_NR_ADC_PINS       15 + +/* Number of pins already connected to external hardware.  For Maple, + * these are just BOARD_LED_PIN and BOARD_BUTTON_PIN. */ +#define BOARD_NR_USED_PINS       7 + +/* + * Debug port pins + */ +#define BOARD_JTMS_SWDIO_PIN    39 +#define BOARD_JTCK_SWCLK_PIN    40 +#define BOARD_JTDI_PIN          41 +#define BOARD_JTDO_PIN          42 +#define BOARD_NJTRST_PIN        43 + +#endif diff --git a/wirish/boards/maple_RET6.cpp b/wirish/boards/maple_RET6.cpp new file mode 100644 index 0000000..d5d3d32 --- /dev/null +++ b/wirish/boards/maple_RET6.cpp @@ -0,0 +1,112 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple_RET6.cpp + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Maple RET6 Edition PIN_MAP and boardInit() + */ + +#include "maple_RET6.h" + +#ifdef BOARD_maple_RET6 + +void boardInit(void) { +} + +extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { + +    /* Top header */ + +    {GPIOA, TIMER2, ADC1,  3, 4,    3}, /* D0/PA3 */ +    {GPIOA, TIMER2, ADC1,  2, 3,    2}, /* D1/PA2 */ +    {GPIOA, TIMER2, ADC1,  0, 1,    0}, /* D2/PA0 */ +    {GPIOA, TIMER2, ADC1,  1, 2,    1}, /* D3/PA1 */ +    {GPIOB,   NULL, NULL,  5, 0, ADCx}, /* D4/PB5 */ +    {GPIOB, TIMER4, NULL,  6, 1, ADCx}, /* D5/PB6 */ +    {GPIOA, TIMER1, NULL,  8, 1, ADCx}, /* D6/PA8 */ +    {GPIOA, TIMER1, NULL,  9, 2, ADCx}, /* D7/PA9 */ +    {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D8/PA10 */ +    {GPIOB, TIMER4, NULL,  7, 2, ADCx}, /* D9/PB7 */ +    {GPIOA,   NULL, ADC1,  4, 0,    4}, /* D10/PA4 */ +    {GPIOA, TIMER3, ADC1,  7, 2,    7}, /* D11/PA7 */ +    {GPIOA, TIMER3, ADC1,  6, 1,    6}, /* D12/PA6 */ +    {GPIOA,   NULL, ADC1,  5, 0,    5}, /* D13/PA5 (LED) */ +    {GPIOB, TIMER4, NULL,  8, 3, ADCx}, /* D14/PB8 */ + +    /* Little header */ + +    {GPIOC,   NULL, ADC1,  0, 0,   10}, /* D15/PC0 */ +    {GPIOC,   NULL, ADC1,  1, 0,   11}, /* D16/PC1 */ +    {GPIOC,   NULL, ADC1,  2, 0,   12}, /* D17/PC2 */ +    {GPIOC,   NULL, ADC1,  3, 0,   13}, /* D18/PC3 */ +    {GPIOC,   NULL, ADC1,  4, 0,   14}, /* D19/PC4 */ +    {GPIOC,   NULL, ADC1,  5, 0,   15}, /* D20/PC5 */ + +    /* External header */ + +    {GPIOC,   NULL, NULL, 13, 0, ADCx}, /* D21/PC13 */ +    {GPIOC,   NULL, NULL, 14, 0, ADCx}, /* D22/PC14 */ +    {GPIOC,   NULL, NULL, 15, 0, ADCx}, /* D23/PC15 */ +    {GPIOB, TIMER4, NULL,  9, 4, ADCx}, /* D24/PB9 */ +    {GPIOD,   NULL, NULL,  2, 0, ADCx}, /* D25/PD2 */ +    {GPIOC,   NULL, NULL, 10, 0, ADCx}, /* D26/PC10 */ +    {GPIOB, TIMER3, ADC1,  0, 3,    8}, /* D27/PB0 */ +    {GPIOB, TIMER3, ADC1,  1, 4,    9}, /* D28/PB1 */ +    {GPIOB,   NULL, NULL, 10, 0, ADCx}, /* D29/PB10 */ +    {GPIOB,   NULL, NULL, 11, 0, ADCx}, /* D30/PB11 */ +    {GPIOB,   NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */ +    {GPIOB,   NULL, NULL, 13, 0, ADCx}, /* D32/PB13 */ +    {GPIOB,   NULL, NULL, 14, 0, ADCx}, /* D33/PB14 */ +    {GPIOB,   NULL, NULL, 15, 0, ADCx}, /* D34/PB15 */ +    {GPIOC, TIMER8, NULL,  6, 1, ADCx}, /* D35/PC6 */ +    {GPIOC, TIMER8, NULL,  7, 2, ADCx}, /* D36/PC7 */ +    {GPIOC, TIMER8, NULL,  8, 3, ADCx}, /* D37/PC8 */ +    {GPIOC, TIMER8, NULL,  9, 4, ADCx}, /* D38/PC9 (BUT) */ + +    /* JTAG header */ + +    {GPIOA,   NULL, NULL, 13, 0, ADCx}, /* D39/PA13 */ +    {GPIOA,   NULL, NULL, 14, 0, ADCx}, /* D40/PA14 */ +    {GPIOA,   NULL, NULL, 15, 0, ADCx}, /* D41/PA15 */ +    {GPIOB,   NULL, NULL,  3, 0, ADCx}, /* D42/PB3  */ +    {GPIOB,   NULL, NULL,  4, 0, ADCx}, /* D43/PB4  */ +}; + +extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { +    0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 24, 25, 27, 28 +}; + +extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = { +    0, 1, 2, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 27, 28 +}; + +extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { +    BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN, +    BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN +}; + +#endif diff --git a/wirish/boards/maple_RET6.h b/wirish/boards/maple_RET6.h new file mode 100644 index 0000000..4195857 --- /dev/null +++ b/wirish/boards/maple_RET6.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple_RET6.h + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Private include file for Maple RET6 Edition in boards.h + * + * See maple.h for more information on these definitions. + */ + +#include "gpio.h" +#include "timer.h" + +#include "wirish_types.h" + +#ifndef _BOARDS_MAPLE_RET6_H_ +#define _BOARDS_MAPLE_RET6_H_ + +#define CYCLES_PER_MICROSECOND  72 +#define SYSTICK_RELOAD_VAL      71999 /* takes a cycle to reload */ + +#define BOARD_BUTTON_PIN        38 +#define BOARD_LED_PIN           13 + +/* Note: UART4 and UART5 have pins which aren't broken out :( */ +#define BOARD_NR_USARTS         3 +#define BOARD_USART1_TX_PIN     7 +#define BOARD_USART1_RX_PIN     8 +#define BOARD_USART2_TX_PIN     1 +#define BOARD_USART2_RX_PIN     0 +#define BOARD_USART3_TX_PIN     29 +#define BOARD_USART3_RX_PIN     30 + +#define BOARD_NR_SPI            2 +#define BOARD_SPI1_NSS_PIN      10 +#define BOARD_SPI1_MOSI_PIN     11 +#define BOARD_SPI1_MISO_PIN     12 +#define BOARD_SPI1_SCK_PIN      13 +#define BOARD_SPI2_NSS_PIN      31 +#define BOARD_SPI2_MOSI_PIN     34 +#define BOARD_SPI2_MISO_PIN     33 +#define BOARD_SPI2_SCK_PIN      32 + +#define BOARD_NR_GPIO_PINS      44 +#define BOARD_NR_PWM_PINS       16 +#define BOARD_NR_ADC_PINS       15 +#define BOARD_NR_USED_PINS      7 + +#define BOARD_JTMS_SWDIO_PIN    39 +#define BOARD_JTCK_SWCLK_PIN    40 +#define BOARD_JTDI_PIN          41 +#define BOARD_JTDO_PIN          42 +#define BOARD_NJTRST_PIN        43 + +#endif diff --git a/wirish/boards/maple_mini.cpp b/wirish/boards/maple_mini.cpp new file mode 100644 index 0000000..3bc250b --- /dev/null +++ b/wirish/boards/maple_mini.cpp @@ -0,0 +1,103 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple_mini.cpp + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Maple Mini PIN_MAP and boardInit(). + */ + +#include "maple_mini.h" +#include "gpio.h" +#include "wirish_debug.h" + +#ifdef BOARD_maple_mini + +/* Since we want the Serial Wire/JTAG pins as GPIOs, disable both SW + * and JTAG debug support */ +void boardInit(void) { +    disableDebugPorts(); +} + +extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { + +    /* Top header */ + +    {GPIOB,   NULL, NULL, 11, 0, ADCx}, /* D0/PB11 */ +    {GPIOB,   NULL, NULL, 10, 0, ADCx}, /* D1/PB10 */ +    {GPIOB,   NULL, NULL,  2, 0, ADCx}, /* D2/PB2 */ +    {GPIOB, TIMER3, ADC1,  0, 3,    8}, /* D3/PB0 */ +    {GPIOA, TIMER3, ADC1,  7, 2,    7}, /* D4/PA7 */ +    {GPIOA, TIMER3, ADC1,  6, 1,    6}, /* D5/PA6 */ +    {GPIOA,   NULL, ADC1,  5, 0,    5}, /* D6/PA5 */ +    {GPIOA,   NULL, ADC1,  4, 0,    4}, /* D7/PA4 */ +    {GPIOA, TIMER2, ADC1,  3, 4,    3}, /* D8/PA3 */ +    {GPIOA, TIMER2, ADC1,  2, 3,    2}, /* D9/PA2 */ +    {GPIOA, TIMER2, ADC1,  1, 2,    1}, /* D10/PA1 */ +    {GPIOA, TIMER2, ADC1,  0, 1,    0}, /* D11/PA0 */ +    {GPIOC,   NULL, NULL, 15, 0, ADCx}, /* D12/PC15 */ +    {GPIOC,   NULL, NULL, 14, 0, ADCx}, /* D13/PC14 */ +    {GPIOC,   NULL, NULL, 13, 0, ADCx}, /* D14/PC13 */ + +    /* Bottom header */ + +    {GPIOB, TIMER4, NULL,  7, 2, ADCx}, /* D15/PB7 */ +    {GPIOB, TIMER4, NULL,  6, 1, ADCx}, /* D16/PB6 */ +    {GPIOB,   NULL, NULL,  5, 0, ADCx}, /* D17/PB5 */ +    {GPIOB,   NULL, NULL,  4, 0, ADCx}, /* D18/PB4 */ +    {GPIOB,   NULL, NULL,  3, 0, ADCx}, /* D19/PB3 */ +    {GPIOA,   NULL, NULL, 15, 0, ADCx}, /* D20/PA15 */ +    {GPIOA,   NULL, NULL, 14, 0, ADCx}, /* D21/PA14 */ +    {GPIOA,   NULL, NULL, 13, 0, ADCx}, /* D22/PA13 */ +    {GPIOA,   NULL, NULL, 12, 0, ADCx}, /* D23/PA12 */ +    {GPIOA, TIMER1, NULL, 11, 4, ADCx}, /* D24/PA11 */ +    {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D25/PA10 */ +    {GPIOA, TIMER1, NULL,  9, 2, ADCx}, /* D26/PA9 */ +    {GPIOA, TIMER1, NULL,  8, 1, ADCx}, /* D27/PA8 */ +    {GPIOB,   NULL, NULL, 15, 0, ADCx}, /* D28/PB15 */ +    {GPIOB,   NULL, NULL, 14, 0, ADCx}, /* D29/PB14 */ +    {GPIOB,   NULL, NULL, 13, 0, ADCx}, /* D30/PB13 */ +    {GPIOB,   NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */ +    {GPIOB, TIMER4, NULL,  8, 3, ADCx}, /* D32/PB8 */ +    {GPIOB, TIMER3, ADC1,  1, 4,    9}, /* D33/PB1 */ +}; + +extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { +    3, 4, 5, 8, 9, 10, 11, 15, 16, 25, 26, 27 +}; + +extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = { +    3, 4, 5, 6, 7, 8, 9, 10, 11, 33  // NB: 33 is BOARD_LED_PIN +}; + +#define USB_DP 23 +#define USB_DM 24 + +extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { +    BOARD_LED_PIN, BOARD_BUTTON_PIN, USB_DP, USB_DM +}; + +#endif diff --git a/wirish/boards/maple_mini.h b/wirish/boards/maple_mini.h new file mode 100644 index 0000000..fde7f98 --- /dev/null +++ b/wirish/boards/maple_mini.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple_mini.h + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Private include file for Maple Mini in boards.h + * + * See maple.h for more information on these definitions. + */ + +#include "gpio.h" +#include "timer.h" + +#include "wirish_types.h" + +#ifndef _BOARD_MAPLE_MINI_H_ +#define _BOARD_MAPLE_MINI_H_ + +#define CYCLES_PER_MICROSECOND    72 +#define SYSTICK_RELOAD_VAL     71999 /* takes a cycle to reload */ + +#define BOARD_BUTTON_PIN          32 +#define BOARD_LED_PIN             33 + +#define BOARD_NR_USARTS           3 +#define BOARD_USART1_TX_PIN       26 +#define BOARD_USART1_RX_PIN       25 +#define BOARD_USART2_TX_PIN       9 +#define BOARD_USART2_RX_PIN       8 +#define BOARD_USART3_TX_PIN       1 +#define BOARD_USART3_RX_PIN       0 + +#define BOARD_NR_SPI              2 +#define BOARD_SPI1_NSS_PIN        7 +#define BOARD_SPI1_MOSI_PIN       4 +#define BOARD_SPI1_MISO_PIN       5 +#define BOARD_SPI1_SCK_PIN        6 +#define BOARD_SPI2_NSS_PIN        31 +#define BOARD_SPI2_MOSI_PIN       28 +#define BOARD_SPI2_MISO_PIN       29 +#define BOARD_SPI2_SCK_PIN        30 + +#define BOARD_NR_GPIO_PINS        34 +#define BOARD_NR_PWM_PINS         12 +#define BOARD_NR_ADC_PINS         10 +#define BOARD_NR_USED_PINS         4 + +#define BOARD_JTMS_SWDIO_PIN      22 +#define BOARD_JTCK_SWCLK_PIN      21 +#define BOARD_JTDI_PIN            20 +#define BOARD_JTDO_PIN            19 +#define BOARD_NJTRST_PIN          18 + +#endif diff --git a/wirish/boards/maple_native.cpp b/wirish/boards/maple_native.cpp new file mode 100644 index 0000000..fa36240 --- /dev/null +++ b/wirish/boards/maple_native.cpp @@ -0,0 +1,199 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple_native.cpp + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Maple Native PIN_MAP and boardInit(). + */ + +#include "maple_native.h" + +#include "fsmc.h" +#include "gpio.h" +#include "rcc.h" +#include "timer.h" + +#include "wirish_types.h" + +#ifdef BOARD_maple_native + +void initSRAMChip(void); + +void boardInit(void) { +    initSRAMChip(); +} + +extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { + +    /* Top header */ + +    {GPIOB,   NULL, NULL, 10, 0, ADCx}, /* D0/PB10 */ +    {GPIOB,   NULL, NULL, 11, 0, ADCx}, /* D1/PB11 */ +    {GPIOB,   NULL, NULL, 12, 0, ADCx}, /* D2/PB12 */ +    {GPIOB,   NULL, NULL, 13, 0, ADCx}, /* D3/PB13 */ +    {GPIOB,   NULL, NULL, 14, 0, ADCx}, /* D4/PB14 */ +    {GPIOB,   NULL, NULL, 15, 0, ADCx}, /* D5/PB15 */ +    {GPIOG,   NULL, NULL, 15, 0, ADCx}, /* D6/PG15 (BUT) */ +    {GPIOC,   NULL, ADC1,  0, 0,   10}, /* D7/PC0 */ +    {GPIOC,   NULL, ADC1,  1, 0,   11}, /* D8/PC1 */ +    {GPIOC,   NULL, ADC1,  2, 0,   12}, /* D9/PC2 */ +    {GPIOC,   NULL, ADC1,  3, 0,   13}, /* D10/PC3 */ +    {GPIOC,   NULL, ADC1,  4, 0,   14}, /* D11/PC4 */ +    {GPIOC,   NULL, ADC1,  5, 0,   15}, /* D12/PC5 */ +    {GPIOC, TIMER8, NULL,  6, 1, ADCx}, /* D13/PC6 */ +    {GPIOC, TIMER8, NULL,  7, 2, ADCx}, /* D14/PC7 */ +    {GPIOC, TIMER8, NULL,  8, 3, ADCx}, /* D15/PC8 */ +    {GPIOC, TIMER8, NULL,  9, 4, ADCx}, /* D16/PC9 */ +    {GPIOC,   NULL, NULL, 10, 0, ADCx}, /* D17/PC10 */ +    {GPIOC,   NULL, NULL, 11, 0, ADCx}, /* D18/PC11 */ +    {GPIOC,   NULL, NULL, 12, 0, ADCx}, /* D19/PC12 */ +    {GPIOC,   NULL, NULL, 13, 0, ADCx}, /* D20/PC13 */ +    {GPIOC,   NULL, NULL, 14, 0, ADCx}, /* D21/PC14 */ +    {GPIOC,   NULL, NULL, 15, 0, ADCx}, /* D22/PC15 (LED) */ +    {GPIOA, TIMER1, NULL,  8, 1, ADCx}, /* D23/PA8 */ +    {GPIOA, TIMER1, NULL,  9, 2, ADCx}, /* D24/PA9 */ +    {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D25/PA10 */ +    {GPIOB, TIMER4, NULL,  9, 4, ADCx}, /* D26/PB9 */ + +    /* Bottom header */ +    /* Note: D{48, 49, 50, 51} are also TIMER2_CH{1, 2, 3, 4}, respectively. */ +    /* TODO remap timer 2 in boardInit(); make the appropriate changes here */ + +    {GPIOD,   NULL, NULL,  2, 0, ADCx}, /* D27/PD2 */ +    {GPIOD,   NULL, NULL,  3, 0, ADCx}, /* D28/PD3 */ +    {GPIOD,   NULL, NULL,  6, 0, ADCx}, /* D29/PD6 */ +    {GPIOG,   NULL, NULL, 11, 0, ADCx}, /* D30/PG11 */ +    {GPIOG,   NULL, NULL, 12, 0, ADCx}, /* D31/PG12 */ +    {GPIOG,   NULL, NULL, 13, 0, ADCx}, /* D32/PG13 */ +    {GPIOG,   NULL, NULL, 14, 0, ADCx}, /* D33/PG14 */ +    {GPIOG,   NULL, NULL,  8, 0, ADCx}, /* D34/PG8 */ +    {GPIOG,   NULL, NULL,  7, 0, ADCx}, /* D35/PG7 */ +    {GPIOG,   NULL, NULL,  6, 0, ADCx}, /* D36/PG6 */ +    {GPIOB,   NULL, NULL,  5, 0, ADCx}, /* D37/PB5 */ +    {GPIOB, TIMER4, NULL,  6, 1, ADCx}, /* D38/PB6 */ +    {GPIOB, TIMER4, NULL,  7, 2, ADCx}, /* D39/PB7 */ +    {GPIOF,   NULL, NULL, 11, 0, ADCx}, /* D40/PF11 */ +    {GPIOF,   NULL, ADC3,  6, 0,    4}, /* D41/PF6 */ +    {GPIOF,   NULL, ADC3,  7, 0,    5}, /* D42/PF7 */ +    {GPIOF,   NULL, ADC3,  8, 0,    6}, /* D43/PF8 */ +    {GPIOF,   NULL, ADC3,  9, 0,    7}, /* D44/PF9 */ +    {GPIOF,   NULL, ADC3, 10, 0,    8}, /* D45/PF10 */ +    {GPIOB, TIMER3, ADC1,  1, 4,    9}, /* D46/PB1 */ +    {GPIOB, TIMER3, ADC1,  0, 3,    8}, /* D47/PB0 */ +    {GPIOA, TIMER5, ADC1,  0, 1,    0}, /* D48/PA0 */ +    {GPIOA, TIMER5, ADC1,  1, 2,    1}, /* D49/PA1 */ +    {GPIOA, TIMER5, ADC1,  2, 3,    2}, /* D50/PA2 */ +    {GPIOA, TIMER5, ADC1,  3, 4,    3}, /* D51/PA3 */ +    {GPIOA,   NULL, ADC1,  4, 0,    4}, /* D52/PA4 */ +    {GPIOA,   NULL, ADC1,  5, 0,    5}, /* D53/PA5 */ +    {GPIOA, TIMER3, ADC1,  6, 1,    6}, /* D54/PA6 */ +    {GPIOA, TIMER3, ADC1,  7, 2,    7}, /* D55/PA7 */ + +    /* Right (triple) header */ + +    {GPIOF,   NULL, NULL,  0, 0, ADCx}, /* D56/PF0 */ +    {GPIOD,   NULL, NULL, 11, 0, ADCx}, /* D57/PD11 */ +    {GPIOD,   NULL, NULL, 14, 0, ADCx}, /* D58/PD14 */ +    {GPIOF,   NULL, NULL,  1, 0, ADCx}, /* D59/PF1 */ +    {GPIOD,   NULL, NULL, 12, 0, ADCx}, /* D60/PD12 */ +    {GPIOD,   NULL, NULL, 15, 0, ADCx}, /* D61/PD15 */ +    {GPIOF,   NULL, NULL,  2, 0, ADCx}, /* D62/PF2 */ +    {GPIOD,   NULL, NULL, 13, 0, ADCx}, /* D63/PD13 */ +    {GPIOD,   NULL, NULL,  0, 0, ADCx}, /* D64/PD0 */ +    {GPIOF,   NULL, NULL,  3, 0, ADCx}, /* D65/PF3 */ +    {GPIOE,   NULL, NULL,  3, 0, ADCx}, /* D66/PE3 */ +    {GPIOD,   NULL, NULL,  1, 0, ADCx}, /* D67/PD1 */ +    {GPIOF,   NULL, NULL,  4, 0, ADCx}, /* D68/PF4 */ +    {GPIOE,   NULL, NULL,  4, 0, ADCx}, /* D69/PE4 */ +    {GPIOE,   NULL, NULL,  7, 0, ADCx}, /* D70/PE7 */ +    {GPIOF,   NULL, NULL,  5, 0, ADCx}, /* D71/PF5 */ +    {GPIOE,   NULL, NULL,  5, 0, ADCx}, /* D72/PE5 */ +    {GPIOE,   NULL, NULL,  8, 0, ADCx}, /* D73/PE8 */ +    {GPIOF,   NULL, NULL, 12, 0, ADCx}, /* D74/PF12 */ +    {GPIOE,   NULL, NULL,  6, 0, ADCx}, /* D75/PE6 */ +    {GPIOE,   NULL, NULL,  9, 0, ADCx}, /* D76/PE9 */ +    {GPIOF,   NULL, NULL, 13, 0, ADCx}, /* D77/PF13 */ +    {GPIOE,   NULL, NULL, 10, 0, ADCx}, /* D78/PE10 */ +    {GPIOF,   NULL, NULL, 14, 0, ADCx}, /* D79/PF14 */ +    {GPIOG,   NULL, NULL,  9, 0, ADCx}, /* D80/PG9 */ +    {GPIOE,   NULL, NULL, 11, 0, ADCx}, /* D81/PE11 */ +    {GPIOF,   NULL, NULL, 15, 0, ADCx}, /* D82/PF15 */ +    {GPIOG,   NULL, NULL, 10, 0, ADCx}, /* D83/PG10 */ +    {GPIOE,   NULL, NULL, 12, 0, ADCx}, /* D84/PE12 */ +    {GPIOG,   NULL, NULL,  0, 0, ADCx}, /* D85/PG0 */ +    {GPIOD,   NULL, NULL,  5, 0, ADCx}, /* D86/PD5 */ +    {GPIOE,   NULL, NULL, 13, 0, ADCx}, /* D87/PE13 */ +    {GPIOG,   NULL, NULL,  1, 0, ADCx}, /* D88/PG1 */ +    {GPIOD,   NULL, NULL,  4, 0, ADCx}, /* D89/PD4 */ +    {GPIOE,   NULL, NULL, 14, 0, ADCx}, /* D90/PE14 */ +    {GPIOG,   NULL, NULL,  2, 0, ADCx}, /* D91/PG2 */ +    {GPIOE,   NULL, NULL,  1, 0, ADCx}, /* D92/PE1 */ +    {GPIOE,   NULL, NULL, 15, 0, ADCx}, /* D93/PE15 */ +    {GPIOG,   NULL, NULL,  3, 0, ADCx}, /* D94/PG3 */ +    {GPIOE,   NULL, NULL,  0, 0, ADCx}, /* D95/PE0 */ +    {GPIOD,   NULL, NULL,  8, 0, ADCx}, /* D96/PD8 */ +    {GPIOG,   NULL, NULL,  4, 0, ADCx}, /* D97/PG4 */ +    {GPIOD,   NULL, NULL,  9, 0, ADCx}, /* D98/PD9 */ +    {GPIOG,   NULL, NULL,  5, 0, ADCx}, /* D99/PG5 */ +    {GPIOD,   NULL, NULL, 10, 0, ADCx}, /* D100/PD10 */ + +    /* JTAG header */ + +    {GPIOA,   NULL, NULL, 13, 0, ADCx}, /* D101/PA13 */ +    {GPIOA,   NULL, NULL, 14, 0, ADCx}, /* D102/PA14 */ +    {GPIOA,   NULL, NULL, 15, 0, ADCx}, /* D103/PA15 */ +    {GPIOB,   NULL, NULL,  3, 0, ADCx}, /* D104/PB3  */ +    {GPIOB,   NULL, NULL,  4, 0, ADCx}  /* D105/PB4  */ +}; + +extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { +    13, 14, 15, 16, 23, 24, 25, 26, 38, 39, 46, 47, 48, 49, 50, 51, 54, 55 +}; + +extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = { +    7, 8, 9, 10, 11, 12, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +    54, 55 +}; + +/* FIXME [0.0.10] see comment by BOARD_NR_USED_PINS in maple_native.h */ +extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { +    BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN, +    BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN +}; + +void initSRAMChip(void) { +    fsmc_nor_psram_reg_map *regs = FSMC_NOR_PSRAM1_BASE; + +    fsmc_sram_init_gpios(); +    rcc_clk_enable(RCC_FSMC); + +    regs->BCR = FSMC_BCR_WREN | FSMC_BCR_MWID_16BITS | FSMC_BCR_MBKEN; +    fsmc_nor_psram_set_addset(regs, 0); +    fsmc_nor_psram_set_datast(regs, 3); +} + +#endif diff --git a/wirish/boards/maple_native.h b/wirish/boards/maple_native.h new file mode 100644 index 0000000..b573d72 --- /dev/null +++ b/wirish/boards/maple_native.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   maple_native.h + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Private include file for Maple Native in boards.h + * + * See maple.h for more information on these definitions. + */ + +#ifndef _BOARD_MAPLE_NATIVE_H_ +#define _BOARD_MAPLE_NATIVE_H_ + +#define CYCLES_PER_MICROSECOND  72 +#define SYSTICK_RELOAD_VAL      71999 + +#define BOARD_LED_PIN           22 +#define BOARD_BUTTON_PIN        6 + +#define BOARD_NR_USARTS         5 +#define BOARD_USART1_TX_PIN     26 +#define BOARD_USART1_RX_PIN     27 +#define BOARD_USART2_TX_PIN     52 +#define BOARD_USART2_RX_PIN     53 +#define BOARD_USART3_TX_PIN     0 +#define BOARD_USART3_RX_PIN     1 +#define BOARD_UART4_TX_PIN      19 +#define BOARD_UART4_RX_PIN      20 +#define BOARD_UART5_TX_PIN      21 +#define BOARD_UART5_RX_PIN      29 + +#define BOARD_NR_SPI            3 +#define BOARD_SPI1_NSS_PIN      52 +#define BOARD_SPI1_MOSI_PIN     55 +#define BOARD_SPI1_MISO_PIN     54 +#define BOARD_SPI1_SCK_PIN      53 +#define BOARD_SPI2_NSS_PIN      2 +#define BOARD_SPI2_MOSI_PIN     5 +#define BOARD_SPI2_MISO_PIN     4 +#define BOARD_SPI2_SCK_PIN      3 +#define BOARD_SPI3_NSS_PIN      103 +#define BOARD_SPI3_MOSI_PIN     37 +#define BOARD_SPI3_MISO_PIN     105 +#define BOARD_SPI3_SCK_PIN      104 + +#define BOARD_NR_GPIO_PINS      106 +#define BOARD_NR_PWM_PINS       18 +#define BOARD_NR_ADC_PINS       21 +/* FIXME [0.0.10] this isn't true at all; almost all of the triple + * header pins are used by the FSMC by default.  Fix this (and the + * corresponding boardUsedPins definition in maple_native.cpp) by QA + * time. */ +#define BOARD_NR_USED_PINS      7 + +#define BOARD_JTMS_SWDIO_PIN    101 +#define BOARD_JTCK_SWCLK_PIN    102 +#define BOARD_JTDI_PIN          103 +#define BOARD_JTDO_PIN          104 +#define BOARD_NJTRST_PIN        105 + +#endif diff --git a/wirish/comm/HardwareSPI.cpp b/wirish/comm/HardwareSPI.cpp index 20090f5..54b7ab3 100644 --- a/wirish/comm/HardwareSPI.cpp +++ b/wirish/comm/HardwareSPI.cpp @@ -23,118 +23,268 @@   *****************************************************************************/  /** - * @brief HardwareSPI "wiring-like" api for SPI + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief Wirish SPI implementation.   */ -/* NOTES: - * - * Speeds: - * ----------------------------------- - * Interface num:     SPI1        SPI2 - * Bus                APB2        APB1 - * ----------------------------------- - * Prescaler         Frequencies - * ----------------------------------- - * 2:                  N/A  18 000 000 - * 4:           18 000 000   9 000 000 - * 8:            9 000 000   4 500 000 - * 16:           4 500 000   2 250 000 - * 32:           2 250 000   1 125 000 - * 64:           1 125 000     562 500 - * 128:            562 500     281 250 - * 256:            281 250     140 625 - * - * TODO: Do the complementary PWM outputs mess up SPI2? - * */ +#include "HardwareSPI.h" + +#include "timer.h" +#include "util.h"  #include "wirish.h" -#include "spi.h" -#include "HardwareSPI.h" +#include "boards.h" -static const uint32 prescaleFactors[MAX_SPI_FREQS] = { -    SPI_PRESCALE_2,               // SPI_18MHZ -    SPI_PRESCALE_4,               // SPI_9MHZ -    SPI_PRESCALE_8,               // SPI_4_5MHZ -    SPI_PRESCALE_16,              // SPI_2_25MHZ -    SPI_PRESCALE_32,              // SPI_1_125MHZ -    SPI_PRESCALE_64,              // SPI_562_500KHZ -    SPI_PRESCALE_128,             // SPI_281_250KHZ -    SPI_PRESCALE_256,             // SPI_140_625KHZ -}; +static void enable_device(spi_dev *dev, +                          bool as_master, +                          SPIFrequency frequency, +                          spi_cfg_flag endianness, +                          spi_mode mode); -/** - * @brief Initialize a SPI peripheral - * @param freq frequency to run at, must one of the following values: - *           - SPI_18MHZ - *           - SPI_9MHZ - *           - SPI_4_5MHZ - *           - SPI_2_25MHZ - *           - SPI_1_125MHZ - *           - SPI_562_500KHZ - *           - SPI_281_250KHZ - *           - SPI_140_625KHZ - * @param endianness endianness of the data frame, must be either LSBFIRST - *           or MSBFIRST - * @param mode SPI standard CPOL and CPHA levels +/* + * Constructor, public methods   */ -void HardwareSPI::begin(SPIFrequency freq, uint32 endianness, uint32 mode) { -    uint32 spi_num    = this->spi_num; -    uint32 prescale; - -    if ((freq >= MAX_SPI_FREQS)     || -        !((endianness == LSBFIRST)  || -          (endianness == MSBFIRST)) || -        (mode >= 4)) { + +HardwareSPI::HardwareSPI(uint32 spi_num) { +    switch (spi_num) { +    case 1: +        this->spi_d = SPI1; +        break; +    case 2: +        this->spi_d = SPI2; +        break; +#ifdef STM32_HIGH_DENSITY +    case 3: +        this->spi_d = SPI3; +        break; +#endif +    default: +        ASSERT(0); +    } +} + +void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) { +    if (mode >= 4) { +        ASSERT(0);          return;      } +    spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; +    spi_mode m = (spi_mode)mode; +    enable_device(this->spi_d, true, frequency, end, m); +} -    if (spi_num == 1) { -        /* SPI1 is too fast for 140625  */ -        if (freq == SPI_140_625KHZ) { -            return; -        } +void HardwareSPI::begin(void) { +    this->begin(SPI_1_125MHZ, MSBFIRST, 0); +} -        /* Turn off PWM on shared pins */ -        timer_set_mode(TIMER3, 2, TIMER_DISABLED); -        timer_set_mode(TIMER3, 1, TIMER_DISABLED); +void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) { +    if (mode >= 4) { +        ASSERT(0); +        return;      } +    spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; +    spi_mode m = (spi_mode)mode; +    enable_device(this->spi_d, false, (SPIFrequency)0, end, m); +} -    endianness = (endianness == LSBFIRST) ? SPI_LSBFIRST : SPI_MSBFIRST; -    prescale = (spi_num == 1) ? -        prescaleFactors[freq + 1] : -        prescaleFactors[freq]; +void HardwareSPI::beginSlave(void) { +    this->beginSlave(MSBFIRST, 0); +} + +void HardwareSPI::end(void) { +    if (!spi_is_enabled(this->spi_d)) { +        return; +    } -    spi_init(spi_num, prescale, endianness, mode); +    // Follows RM0008's sequence for disabling a SPI in master/slave +    // full duplex mode. +    while (spi_is_rx_nonempty(this->spi_d)) { +        // FIXME [0.1.0] remove this once you have an interrupt based driver +        volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); +    } +    while (!spi_is_tx_empty(this->spi_d)) +        ; +    while (spi_is_busy(this->spi_d)) +        ; +    spi_peripheral_disable(this->spi_d);  } -/** - * @brief Initialize a SPI peripheral with a default speed of 1.125 - *      MHZ, MSBFIRST, mode 0 - */ -void HardwareSPI::begin(void) { -   begin(SPI_1_125MHZ, MSBFIRST, 0); +uint8 HardwareSPI::read(void) { +    uint8 buf[1]; +    this->read(buf, 1); +    return buf[0];  } -/** - * @brief send a byte out the spi peripheral - * @param data byte to send +void HardwareSPI::read(uint8 *buf, uint32 len) { +    uint32 rxed = 0; +    while (rxed < len) { +        while (!spi_is_rx_nonempty(this->spi_d)) +            ; +        buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); +    } +} + +void HardwareSPI::write(uint8 byte) { +    this->write(&byte, 1); +} + +void HardwareSPI::write(const uint8 *data, uint32 length) { +    uint32 txed = 0; +    while (txed < length) { +        txed += spi_tx(this->spi_d, data + txed, length - txed); +    } +} + +uint8 HardwareSPI::transfer(uint8 byte) { +    this->write(byte); +    return this->read(); +} + +/* + * Deprecated functions   */ +  uint8 HardwareSPI::send(uint8 data) { -   return spi_tx_byte(this->spi_num, data); +    uint8 buf[] = {data}; +    return this->send(buf, 1);  }  uint8 HardwareSPI::send(uint8 *buf, uint32 len) { -   return spi_tx(this->spi_num, buf, len); +    if (len == 0) { +        return 0; +    } +    uint32 txed = 0; +    uint8 ret = 0;              // shut up, GCC +    while (txed < len) { +        this->write(buf[txed++]); +        ret = this->read(); +    } +    return ret;  } -/** - * @brief read a byte from the spi peripheral - * @return byte in the buffer - */  uint8 HardwareSPI::recv(void) { -   return spi_rx(this->spi_num); +    return this->read();  } -HardwareSPI::HardwareSPI(uint32 spi_num) { -   this->spi_num = spi_num; +/* + * Auxiliary functions + */ + +static void configure_gpios(spi_dev *dev, bool as_master); +static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq); + +/* Enables the device in master or slave full duplex mode.  If you + * change this code, you must ensure that appropriate changes are made + * to HardwareSPI::end(). */ +static void enable_device(spi_dev *dev, +                          bool as_master, +                          SPIFrequency freq, +                          spi_cfg_flag endianness, +                          spi_mode mode) { +    spi_baud_rate baud = determine_baud_rate(dev, freq); +    uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE | +                        (as_master ? SPI_SOFT_SS : 0)); + +    spi_init(dev); +    configure_gpios(dev, as_master); +    if (as_master) { +        spi_master_enable(dev, baud, mode, cfg_flags); +    } else { +        spi_slave_enable(dev, mode, cfg_flags); +    } +} + +static void disable_pwm(const stm32_pin_info *i) { +    if (i->timer_device) { +        timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); +    } +} + +typedef struct spi_pins { +    uint8 nss; +    uint8 sck; +    uint8 miso; +    uint8 mosi; +} spi_pins; + +static void configure_gpios(spi_dev *dev, bool as_master) { +    const spi_pins spi_pin_config[] = { +        {BOARD_SPI1_NSS_PIN, +         BOARD_SPI1_SCK_PIN, +         BOARD_SPI1_MISO_PIN, +         BOARD_SPI1_MOSI_PIN}, +        {BOARD_SPI2_NSS_PIN, +         BOARD_SPI2_SCK_PIN, +         BOARD_SPI2_MISO_PIN, +         BOARD_SPI2_MOSI_PIN}, +#ifdef STM32_HIGH_DENSITY +        {BOARD_SPI3_NSS_PIN, +         BOARD_SPI3_SCK_PIN, +         BOARD_SPI3_MISO_PIN, +         BOARD_SPI3_MOSI_PIN}, +#endif +    }; + +    const spi_pins *pins; + +    switch (dev->clk_id) { +    case RCC_SPI1: +        pins = &spi_pin_config[0]; +        break; +    case RCC_SPI2: +        pins = &spi_pin_config[1]; +        break; +#ifdef STM32_HIGH_DENSITY +    case RCC_SPI3: +        pins = &spi_pin_config[2]; +        break; +#endif +    default: +        ASSERT(0); +        return; +    } + +    const stm32_pin_info *nssi = &PIN_MAP[pins->nss]; +    const stm32_pin_info *scki = &PIN_MAP[pins->sck]; +    const stm32_pin_info *misoi = &PIN_MAP[pins->miso]; +    const stm32_pin_info *mosii = &PIN_MAP[pins->mosi]; + +    disable_pwm(nssi); +    disable_pwm(scki); +    disable_pwm(misoi); +    disable_pwm(mosii); + +    spi_gpio_cfg(as_master, +                 nssi->gpio_device, +                 nssi->gpio_bit, +                 scki->gpio_device, +                 scki->gpio_bit, +                 misoi->gpio_bit, +                 mosii->gpio_bit); +} + +static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = { +    SPI_BAUD_PCLK_DIV_2, +    SPI_BAUD_PCLK_DIV_4, +    SPI_BAUD_PCLK_DIV_8, +    SPI_BAUD_PCLK_DIV_16, +    SPI_BAUD_PCLK_DIV_32, +    SPI_BAUD_PCLK_DIV_64, +    SPI_BAUD_PCLK_DIV_128, +    SPI_BAUD_PCLK_DIV_256, +}; + +/* + * Note: This assumes you're on a LeafLabs-style board + * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). + */ +static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) { +    if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) { +        /* APB2 peripherals are too fast for 140.625 KHz */ +        ASSERT(0); +        return (spi_baud_rate)~0; +    } +    return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ? +            baud_rates[freq + 1] : +            baud_rates[freq]);  } diff --git a/wirish/comm/HardwareSPI.h b/wirish/comm/HardwareSPI.h index 7241d0b..3a6def5 100644 --- a/wirish/comm/HardwareSPI.h +++ b/wirish/comm/HardwareSPI.h @@ -3,60 +3,188 @@   *   * Copyright (c) 2010 Perry Hung.   * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is   * furnished to do so, subject to the following conditions:   * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software.   * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE.   *****************************************************************************/  /** - * @brief HardwareSPI definitions + * @file HardwareSPI.h + * @brief High-level SPI interface + * + * This is a "bare essentials" polling driver for now.   */ +/* TODO [0.1.0] Remove deprecated methods. */ + +#include "libmaple_types.h" +#include "spi.h" + +#include "boards.h" +  #ifndef _HARDWARESPI_H_  #define _HARDWARESPI_H_  /** - * Defines the possible SPI communication speeds. + * @brief Defines the possible SPI communication speeds.   */  typedef enum SPIFrequency {      SPI_18MHZ       = 0, /**< 18 MHz */      SPI_9MHZ        = 1, /**< 9 MHz */      SPI_4_5MHZ      = 2, /**< 4.5 MHz */ -    SPI_2_25MHZ     = 3, /**< 2.25 MHZ */ +    SPI_2_25MHZ     = 3, /**< 2.25 MHz */      SPI_1_125MHZ    = 4, /**< 1.125 MHz */      SPI_562_500KHZ  = 5, /**< 562.500 KHz */      SPI_281_250KHZ  = 6, /**< 281.250 KHz */      SPI_140_625KHZ  = 7, /**< 140.625 KHz */ -    MAX_SPI_FREQS   = 8, /**< The number of SPI frequencies. */  } SPIFrequency; -/* Documented by hand in docs/source/lang/api/hardwarespi.rst; if you -   make any changes, make sure to update this document. */ +#define MAX_SPI_FREQS 8 + +#if CYCLES_PER_MICROSECOND != 72 +/* TODO [0.2.0?] something smarter than this */ +#warn "Unexpected clock speed; SPI frequency calculation will be incorrect" +#endif + +/** + * @brief Wirish SPI interface. + * + * This implementation uses software slave management, so the caller + * is responsible for controlling the slave select line. + */  class HardwareSPI { - private: -    uint32 spi_num; +public: +    /** +     * @param spiPortNumber Number of the SPI port to manage. +     */ +    HardwareSPI(uint32 spiPortNumber); + +    /** +     * @brief Turn on a SPI port and set its GPIO pin modes for use as master. +     * +     * SPI port is enabled in full duplex mode, with software slave management. +     * +     * @param frequency Communication frequency +     * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST (big-endian) +     * @param mode SPI mode to use, one of SPI_MODE_0, SPI_MODE_1, +     *             SPI_MODE_2, and SPI_MODE_3. +     */ +    void begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode); - public: -    HardwareSPI(uint32 spi_num); +    /** +     * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). +     */      void begin(void); -    void begin(SPIFrequency freq, uint32 endianness, uint32 mode); + +    /** +     * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave. +     * +     * SPI port is enabled in full duplex mode, with software slave management. +     * +     * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian) +     * @param mode SPI mode to use +     */ +    void beginSlave(uint32 bitOrder, uint32 mode); + +    /** +     * @brief Equivalent to beginSlave(MSBFIRST, 0). +     */ +    void beginSlave(void); + +    /** +     * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged. +     */ +    void end(void); + +    /** +     * @brief Return the next unread byte. +     * +     * If there is no unread byte waiting, this function will block +     * until one is received. +     */ +    uint8 read(void); + +    /** +     * @brief Read length bytes, storing them into buffer. +     * @param buffer Buffer to store received bytes into. +     * @param length Number of bytes to store in buffer.  This +     *               function will block until the desired number of +     *               bytes have been read. +     */ +    void read(uint8 *buffer, uint32 length); + +    /** +     * @brief Transmit a byte. +     * @param data Byte to transmit. +     */ +    void write(uint8 data); + +    /** +     * @brief Transmit multiple bytes. +     * @param buffer Bytes to transmit. +     * @param length Number of bytes in buffer to transmit. +     */ +    void write(const uint8 *buffer, uint32 length); + +    /** +     * @brief Transmit a byte, then return the next unread byte. +     * +     * This function transmits before receiving. +     * +     * @param data Byte to transmit. +     * @return Next unread byte. +     */ +    uint8 transfer(uint8 data); + +    /* -- The following methods are deprecated --------------------------- */ + +    /** +     * @brief Deprecated. +     * +     * Use HardwareSPI::transfer() instead. +     * +     * @see HardwareSPI::transfer() +     */      uint8 send(uint8 data); + +    /** +     * @brief Deprecated. +     * +     * Use HardwareSPI::write() in combination with +     * HardwareSPI::read() (or HardwareSPI::transfer()) instead. +     * +     * @see HardwareSPI::write() +     * @see HardwareSPI::read() +     * @see HardwareSPI::transfer() +     */      uint8 send(uint8 *data, uint32 length); + +    /** +     * @brief Deprecated. +     * +     * Use HardwareSPI::read() instead. +     * +     * @see HardwareSPI::read() +     */      uint8 recv(void); +private: +    spi_dev *spi_d;  };  #endif diff --git a/wirish/comm/HardwareSerial.cpp b/wirish/comm/HardwareSerial.cpp index d6c7e82..5c9bff6 100644 --- a/wirish/comm/HardwareSerial.cpp +++ b/wirish/comm/HardwareSerial.cpp @@ -24,69 +24,86 @@  /**   * @file HardwareSerial.cpp - * - * @brief Wiring-like serial api + * @brief Wirish serial port implementation.   */ -#include "wirish.h" -#include "HardwareSerial.h" -#include "usart.h"  #include "gpio.h" -#include "timers.h" +#include "timer.h" + +#include "HardwareSerial.h" +#include "boards.h" -HardwareSerial Serial1(USART1, 4500000UL, GPIOA_BASE,  9,10, TIMER1, 2); -HardwareSerial Serial2(USART2, 2250000UL, GPIOA_BASE,  2, 3, TIMER2, 3); -HardwareSerial Serial3(USART3, 2250000UL, GPIOB_BASE, 10,11, TIMER_INVALID, 0); -// TODO: High density device ports +#define TX1 BOARD_USART1_TX_PIN +#define RX1 BOARD_USART1_RX_PIN +#define TX2 BOARD_USART2_TX_PIN +#define RX2 BOARD_USART2_RX_PIN +#define TX3 BOARD_USART3_TX_PIN +#define RX3 BOARD_USART3_RX_PIN +#if defined STM32_HIGH_DENSITY && !defined(BOARD_maple_RET6) +#define TX4 BOARD_UART4_TX_PIN +#define RX4 BOARD_UART4_RX_PIN +#define TX5 BOARD_UART5_TX_PIN +#define RX5 BOARD_UART5_RX_PIN +#endif -HardwareSerial::HardwareSerial(uint8 usart_num, -                               uint32 max_baud, -                               GPIO_Port *gpio_port, +// TODO Put these magic numbers into boards.h #defines +HardwareSerial Serial1(USART1, TX1, RX1, 72000000UL); +HardwareSerial Serial2(USART2, TX2, RX2, 36000000UL); +HardwareSerial Serial3(USART3, TX3, RX3, 36000000UL); +#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) +HardwareSerial Serial4(UART4,  TX4, RX4, 36000000UL); +HardwareSerial Serial5(UART5,  TX5, RX5, 36000000UL); +#endif + +HardwareSerial::HardwareSerial(usart_dev *usart_device,                                 uint8 tx_pin,                                 uint8 rx_pin, -                               timer_dev_num timer_num, -                               uint8 compare_num) { -    this->usart_num = usart_num; -    this->max_baud = max_baud; -    this->gpio_port = gpio_port; +                               uint32 clock_speed) { +    this->usart_device = usart_device; +    this->clock_speed = clock_speed;      this->tx_pin = tx_pin;      this->rx_pin = rx_pin; -    this->timer_num = timer_num; -    this->compare_num = compare_num;  }  uint8 HardwareSerial::read(void) { -    return usart_getc(usart_num); +    return usart_getc(usart_device);  }  uint32 HardwareSerial::available(void) { -    return usart_data_available(usart_num); +    return usart_data_available(usart_device);  }  void HardwareSerial::write(unsigned char ch) { -    usart_putc(usart_num, ch); +    usart_putc(usart_device, ch);  }  void HardwareSerial::begin(uint32 baud) { -    if (baud > max_baud) { +    ASSERT(baud <= usart_device->max_baud); + +    if (baud > usart_device->max_baud) {          return;      } -    gpio_set_mode(gpio_port, tx_pin, GPIO_MODE_AF_OUTPUT_PP); -    gpio_set_mode(gpio_port, rx_pin, GPIO_MODE_INPUT_FLOATING); +    const stm32_pin_info *txi = &PIN_MAP[tx_pin]; +    const stm32_pin_info *rxi = &PIN_MAP[rx_pin]; + +    gpio_set_mode(txi->gpio_device, txi->gpio_bit, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, GPIO_INPUT_FLOATING); -    if (timer_num != TIMER_INVALID) { -        /* turn off any pwm if there's a conflict on this usart */ -        timer_set_mode(timer_num, compare_num, TIMER_DISABLED); +    if (txi->timer_device != NULL) { +        /* Turn off any PWM if there's a conflict on this GPIO bit. */ +        timer_set_mode(txi->timer_device, txi->timer_channel, TIMER_DISABLED);      } -    usart_init(usart_num, baud); +    usart_init(usart_device); +    usart_set_baud_rate(usart_device, clock_speed, baud); +    usart_enable(usart_device);  }  void HardwareSerial::end(void) { -    usart_disable(usart_num); +    usart_disable(usart_device);  }  void HardwareSerial::flush(void) { -    usart_reset_rx(usart_num); +    usart_reset_rx(usart_device);  } diff --git a/wirish/comm/HardwareSerial.h b/wirish/comm/HardwareSerial.h index aad8aa7..934db23 100644 --- a/wirish/comm/HardwareSerial.h +++ b/wirish/comm/HardwareSerial.h @@ -24,41 +24,34 @@  /**   * @file HardwareSerial.h - * - * @brief Wirish interface to hardware serial communications. + * @brief Wirish serial port interface.   */  #ifndef _HARDWARESERIAL_H_  #define _HARDWARESERIAL_H_ -#include "timers.h" +#include "libmaple_types.h" +#include "usart.h"  #include "Print.h" -/* NB: this class documented "by hand" (i.e., not using Doxygen) in: - -     libmaple/docs/source/lang/serial.rst - -   If you alter the public HardwareSerial interface, you must update -   the documentation accordingly. */ +/* + * IMPORTANT: + * + * This class documented "by hand" (i.e., not using Doxygen) in: + * + *   libmaple/docs/source/lang/api/serial.rst + * + * If you alter the public HardwareSerial interface, you MUST update + * the documentation accordingly. + */  class HardwareSerial : public Print { - private: -    uint8 usart_num; -    uint32 max_baud; -    GPIO_Port *gpio_port; -    uint8 tx_pin; -    uint8 rx_pin; -    timer_dev_num timer_num; -    uint8 compare_num; - public: -    HardwareSerial(uint8 usart_num, -                   uint32 max_baud, -                   GPIO_Port *gpio_port, +public: +    HardwareSerial(usart_dev *usart_device,                     uint8 tx_pin,                     uint8 rx_pin, -                   timer_dev_num timer_num, -                   uint8 compare_num); +                   uint32 clock_speed);      void begin(uint32 baud);      void end(void);      uint32 available(void); @@ -66,10 +59,19 @@ class HardwareSerial : public Print {      void flush(void);      virtual void write(unsigned char);      using Print::write; +private: +    usart_dev *usart_device; +    uint8 tx_pin; +    uint8 rx_pin; +    uint32 clock_speed;  }; +  extern HardwareSerial Serial1;  extern HardwareSerial Serial2;  extern HardwareSerial Serial3; -// TODO: high density device ports +#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) +extern HardwareSerial Serial4; +extern HardwareSerial Serial5;  #endif +#endif diff --git a/wirish/ext_interrupts.c b/wirish/ext_interrupts.cpp index dd7c1a8..557fffd 100644 --- a/wirish/ext_interrupts.c +++ b/wirish/ext_interrupts.cpp @@ -28,52 +28,55 @@   *  @brief Wiring-like interface for external interrupts   */ -#include "wirish.h" +#include "boards.h" +#include "gpio.h"  #include "exti.h"  #include "ext_interrupts.h" -/* Attach ISR handler on pin, triggering on the given mode. */ -void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) { -    uint8 outMode; - -    /* Parameter checking */ -    if (pin >= NR_GPIO_PINS) { -        return; -    } +static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode); -    if (!handler) { +/** + * @brief Attach an interrupt handler to a pin, triggering on the given mode. + * @param pin     Pin to attach an interrupt handler onto. + * @param handler Function to call when the external interrupt is triggered. + * @param mode    Trigger mode for the given interrupt. + * @see ExtIntTriggerMode + */ +void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) { +    if (pin >= BOARD_NR_GPIO_PINS || !handler) {          return;      } -    switch (mode) { -    case RISING: -        outMode = EXTI_RISING; -        break; -    case FALLING: -        outMode = EXTI_FALLING; -        break; -    case CHANGE: -        outMode = EXTI_RISING_FALLING; -        break; -    default: -        ASSERT(0); -        return; -    } +    exti_trigger_mode outMode = exti_out_mode(mode); -    exti_attach_interrupt(PIN_MAP[pin].exti_port, -                          PIN_MAP[pin].pin, +    exti_attach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit), +                          gpio_exti_port(PIN_MAP[pin].gpio_device),                            handler, -                          mode); - -    return; +                          outMode);  } -/* Disable any interrupts */ +/** + * @brief Disable any external interrupt attached to a pin. + * @param pin Pin number to detach any interrupt from. + */  void detachInterrupt(uint8 pin) { -    if (!(pin < NR_GPIO_PINS)) { +    if (pin >= BOARD_NR_GPIO_PINS) {          return;      } -    exti_detach_interrupt(PIN_MAP[pin].pin); +    exti_detach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit));  } +static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) { +    switch (mode) { +    case RISING: +        return EXTI_RISING; +    case FALLING: +        return EXTI_FALLING; +    case CHANGE: +        return EXTI_RISING_FALLING; +    } +    // Can't happen +    ASSERT(0); +    return (exti_trigger_mode)0; +} diff --git a/wirish/ext_interrupts.h b/wirish/ext_interrupts.h index 304e267..7d20801 100644 --- a/wirish/ext_interrupts.h +++ b/wirish/ext_interrupts.h @@ -28,7 +28,7 @@  /**   *  @file ext_interrupts.h   * - *  @brief External interrupt wiring prototypes and types + *  @brief Wiring-like external interrupt prototypes and types.   */  #ifndef _EXT_INTERRUPTS_H_ @@ -38,7 +38,7 @@   * The kind of transition on an external pin which should trigger an   * interrupt.   */ -typedef enum ExtIntTriggerMode_ { +typedef enum ExtIntTriggerMode {      RISING, /**< To trigger an interrupt when the pin transitions LOW                 to HIGH */      FALLING, /**< To trigger an interrupt when the pin transitions @@ -48,10 +48,6 @@ typedef enum ExtIntTriggerMode_ {                changes). */  } ExtIntTriggerMode; -#ifdef __cplusplus -extern "C"{ -#endif -  /**   *  @brief Registers an interrupt handler on a pin.   * @@ -86,7 +82,7 @@ void detachInterrupt(uint8 pin);   *   * @see noInterrupts()   */ -static ALWAYS_INLINE void interrupts() { +static inline void interrupts() {      nvic_globalirq_enable();  } @@ -100,14 +96,9 @@ static ALWAYS_INLINE void interrupts() {   *   * @see interrupts()   */ -static ALWAYS_INLINE void noInterrupts() { +static inline void noInterrupts() {      nvic_globalirq_disable();  } -#ifdef __cplusplus -} -#endif - -  #endif diff --git a/wirish/io.h b/wirish/io.h index 2d22dcd..ace40f2 100644 --- a/wirish/io.h +++ b/wirish/io.h @@ -28,30 +28,16 @@   *  @brief Arduino-compatible digital pin I/O interface.   */ -#ifndef _IO_H -#define _IO_H +#ifndef _IO_H_ +#define _IO_H_  #include "gpio.h"  #include "adc.h" -#include "time.h" -#ifdef __cplusplus -extern "C"{ -#endif +#include "wirish_time.h"  /**   * Specifies a GPIO pin behavior. - * - * Each of the GPIO pins on a Maple board may be configured using - * pinMode() to behave in a number of ways: as a digital output pin, - * or as an analog input pin, etc., depending on the particular pin. - * - * This enum specifies the complete set of possible configurations; - * not every pin can have all of these modes.  For example, on the - * Maple, pin 15 may be configured as INPUT_ANALOG, but not as PWM. - * See your device's silkscreen and and the GPIO documentation for - * more information. - *   * @see pinMode()   */  typedef enum WiringPinMode { @@ -68,11 +54,11 @@ typedef enum WiringPinMode {                            supply through a large resistor). When the                            pin is high, not much current flows through                            to ground and the line stays at positive -                          voltage; when the pin is low the bus +                          voltage; when the pin is low, the bus                            "drains" to ground with a small amount of                            current constantly flowing through the large                            resistor from the external supply. In this -                          mode no current is ever actually /sourced/ +                          mode, no current is ever actually sourced                            from the pin. */      INPUT, /**< Basic digital input. The pin voltage is sampled; when @@ -118,8 +104,7 @@ typedef enum WiringPinMode {  /**   * Configure behavior of a GPIO pin.   * - * @param pin Pin to configure. One of: 0-38 (pin numbers as labeled - *            on silkscreen), or D0-D38 (symbols for same) + * @param pin Number of pin to configure.   * @param mode Mode corresponding to desired pin behavior.   * @see WiringPinMode   */ @@ -127,10 +112,9 @@ void pinMode(uint8 pin, WiringPinMode mode);  /**   * Writes a (digital) value to a pin.  The pin must have its - * mode set to <code>OUTPUT</code> or <code>OUTPUT_OPEN_DRAIN</code>. + * mode set to OUTPUT or OUTPUT_OPEN_DRAIN.   * - * @param pin Pin to write to. One of: 0-38 (pin numbers as labeled - *            on silkscreen), or D0-D38 (symbols for same) + * @param pin Pin to write to.   * @param value Either LOW (write a 0) or HIGH (write a 1).   * @see pinMode()   */ @@ -140,8 +124,7 @@ void digitalWrite(uint8 pin, uint8 value);   * Read a digital value from a pin.  The pin must have its mode set to   * one of INPUT, INPUT_PULLUP, and INPUT_PULLDOWN.   * - * @param pin Pin to read from. One of: 0-38 (pin numbers as labeled - *            on silkscreen), or D0-D38 (symbols for same) + * @param pin Pin to read from.   * @return LOW or HIGH.   * @see pinMode()   */ @@ -150,18 +133,14 @@ uint32 digitalRead(uint8 pin);  /**   * Read an analog value from pin.  This function blocks during ADC   * conversion, and has 12 bits of resolution.  The pin must have its - * mode set to INPUT_ANALOG.  Ignoring function call overhead, - * conversion time is 55.5 cycles. + * mode set to INPUT_ANALOG.   * - * @param pin Pin to read from. One of: 0, 1, 2, 3, 10, 11, 12, 13, - * 15, 16, 17, 18, 19, 20, 27, 28. - - * @return ADC-converted voltage, in the range 0--4095, inclusive - * (i.e. a 12-bit ADC conversion). - + * @param pin Pin to read from. + * @return Converted voltage, in the range 0--4095, (i.e. a 12-bit ADC + *         conversion).   * @see pinMode()   */ -uint32 analogRead(uint8 pin); +uint16 analogRead(uint8 pin);  /**   * Toggles the digital value at the given pin. @@ -211,17 +190,31 @@ uint8 isButtonPressed();   * pinMode(BOARD_BUTTON_PIN, INPUT).   *   * @param timeout_millis Number of milliseconds to wait until the - * button is pressed.  If timeout_millis is 0, wait forever. + * button is pressed.  If timeout_millis is left out (or 0), wait + * forever.   *   * @return true, if the button was pressed; false, if the timeout was   * reached.   *   * @see pinMode()   */ -uint8 waitForButtonPress(uint32 timeout_millis); +uint8 waitForButtonPress(uint32 timeout_millis=0); + +/** + * Shift out a byte of data, one bit at a time. + * + * This function starts at either the most significant or least + * significant bit in a byte value, and shifts out each byte in order + * onto a data pin.  After each bit is written to the data pin, a + * separate clock pin is pulsed to indicate that the new bit is + * available. + * + * @param dataPin  Pin to shift data out on + * @param clockPin Pin to pulse after each bit is shifted out + * @param bitOrder Either MSBFIRST (big-endian) or LSBFIRST (little-endian). + * @param value    Value to shift out + */ +void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value); -#ifdef __cplusplus -} // extern "C" -#endif  #endif diff --git a/wirish/main.cxx b/wirish/main.cxx index f0158f8..dd5e296 100644 --- a/wirish/main.cxx +++ b/wirish/main.cxx @@ -1,4 +1,4 @@ -/* *****************************************************************************
 +/******************************************************************************
   * The MIT License
   *
   * Copyright (c) 2010 LeafLabs LLC.
 @@ -20,16 +20,15 @@   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
 - * ****************************************************************************/
 + *****************************************************************************/
  // Force init to be called *first*, i.e. before static object allocation.
 -// Otherwise, statically allocated object that need libmaple may fail.
 +// Otherwise, statically allocated objects that need libmaple may fail.
   __attribute__(( constructor )) void premain() {
      init();
  }
 -int main(void)
 -{
 +int main(void) {
      setup();
      while (1) {
 diff --git a/wirish/pwm.c b/wirish/pwm.cpp index 072e4cd..bf69bfb 100644 --- a/wirish/pwm.c +++ b/wirish/pwm.cpp @@ -23,26 +23,20 @@   *****************************************************************************/  /** - *  @brief Arduino-compatible PWM implementation. + *  @brief Arduino-style PWM implementation.   */ -#include "wirish.h" -#include "timers.h" -#include "io.h" +#include "libmaple_types.h" +#include "timer.h" + +#include "boards.h"  #include "pwm.h"  void pwmWrite(uint8 pin, uint16 duty_cycle) { -    TimerCCR ccr; - -    if (pin >= NR_GPIO_PINS) { -        return; -    } - -    ccr = PIN_MAP[pin].timer_ccr; - -    if (ccr == 0) { +    timer_dev *dev = PIN_MAP[pin].timer_device; +    if (pin >= BOARD_NR_GPIO_PINS || dev == NULL || dev->type == TIMER_BASIC) {          return;      } -    timer_pwm_write_ccr(ccr, duty_cycle); +    timer_set_compare(dev, PIN_MAP[pin].timer_channel, duty_cycle);  } diff --git a/wirish/pwm.h b/wirish/pwm.h index d0bc9e0..4ce4bb4 100644 --- a/wirish/pwm.h +++ b/wirish/pwm.h @@ -28,12 +28,8 @@   *  @brief Arduino-compatible PWM interface.   */ -#ifndef _PWM_H -#define _PWM_H - -#ifdef __cplusplus -extern "C"{ -#endif +#ifndef _PWM_H_ +#define _PWM_H_  /**   * As a convenience, analogWrite is an alias of pwmWrite to ease @@ -47,13 +43,11 @@ extern "C"{   *   * User code is expected to determine and honor the maximum value   * (based on the configured period). + * + * @param pin PWM output pin + * @param duty_cycle Duty cycle to set.   */  void pwmWrite(uint8 pin, uint16 duty_cycle); -#ifdef __cplusplus -} -#endif - -  #endif diff --git a/wirish/rules.mk b/wirish/rules.mk index cb5a69f..6999288 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -4,30 +4,36 @@ dirstack_$(sp)  := $(d)  d               := $(dir)  BUILDDIRS       += $(BUILD_PATH)/$(d)  BUILDDIRS       += $(BUILD_PATH)/$(d)/comm +BUILDDIRS       += $(BUILD_PATH)/$(d)/boards -WIRISH_INCLUDES := -I$(d) -I$(d)/comm +WIRISH_INCLUDES := -I$(d) -I$(d)/comm -I$(d)/boards  # Local flags  CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES)  # Local rules and targets -cSRCS_$(d) :=  wirish.c 	       \ -               wirish_shift.c          \ -               wirish_analog.c         \ -               time.c 		       \ -               pwm.c 		       \ -               ext_interrupts.c        \ -               wirish_digital.c - -cppSRCS_$(d) := wirish_math.cpp          \ -                Print.cpp 		 \ -                comm/HardwareSerial.cpp  \ -                comm/HardwareSPI.cpp 	 \ -                usb_serial.cpp 	         \ -		HardwareTimer.cpp        \ -                cxxabi-compat.cpp        \ - -cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) +cSRCS_$(d) :=   + +cppSRCS_$(d) := wirish_math.cpp		 \ +                Print.cpp		 \ +		boards.cpp               \ +                boards/maple.cpp	 \ +                boards/maple_mini.cpp	 \ +                boards/maple_native.cpp	 \ +                boards/maple_RET6.cpp	 \ +                comm/HardwareSerial.cpp	 \ +                comm/HardwareSPI.cpp	 \ +		HardwareTimer.cpp	 \ +                usb_serial.cpp		 \ +                cxxabi-compat.cpp	 \ +		wirish_shift.cpp	 \ +		wirish_analog.cpp	 \ +		wirish_time.cpp		 \ +		pwm.cpp 		 \ +		ext_interrupts.cpp	 \ +		wirish_digital.cpp + +cFILES_$(d)   := $(cSRCS_$(d):%=$(d)/%)  cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%)  OBJS_$(d)     := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \ diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp index e2cdee3..0a2be43 100644 --- a/wirish/usb_serial.cpp +++ b/wirish/usb_serial.cpp @@ -3,28 +3,29 @@   *   * Copyright (c) 2010 Perry Hung.   * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is   * furnished to do so, subject to the following conditions:   * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software.   * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE.   *****************************************************************************/  /** - *  @brief Wirish USB class for easy communication, uses libmaple's - *  virtual com port implementation + * @brief USB virtual serial terminal   */  #include <string.h> @@ -34,7 +35,7 @@  #define USB_TIMEOUT 50 -USBSerial :: USBSerial(void) { +USBSerial::USBSerial(void) {  }  void USBSerial::begin(void) { @@ -46,54 +47,29 @@ void USBSerial::end(void) {  }  void USBSerial::write(uint8 ch) { -    if(!(usbIsConnected() && usbIsConfigured())) { -        return; -    } - -    uint16 status = 0; -    uint32 start = millis(); - -    while(status == 0 && (millis() - start <= USB_TIMEOUT)) { -        status = usbSendBytes(&ch, 1); -    } +    const uint8 buf[] = {ch}; +    this->write(buf, 1);  }  void USBSerial::write(const char *str) { -    if(!(usbIsConnected() && usbIsConfigured())) { -        return; -    } - -    uint32 len = strlen(str); -    uint16 status = 0; -    uint16 oldstatus = 0; -    uint32 start = millis(); - -    while(status < len && (millis() - start < USB_TIMEOUT)) { -        status += usbSendBytes((uint8*)str+status, len-status); -        if(oldstatus != status) -            start = millis(); -        oldstatus = status; -    } +    this->write(str, strlen(str));  } -void USBSerial::write(void *buf, uint32 size) { -    if(!(usbIsConnected() && usbIsConfigured())) { +void USBSerial::write(const void *buf, uint32 len) { +    if (!(usbIsConnected() && usbIsConfigured()) || !buf) {          return;      } -    if (!buf) { -        return; -    } - -    uint16 status = 0; -    uint16 oldstatus = 0; +    uint32 txed = 0; +    uint32 old_txed = 0;      uint32 start = millis(); -    while(status < size && (millis() - start < USB_TIMEOUT)) { -        status += usbSendBytes((uint8*)buf+status, size-status); -        if(oldstatus != status) +    while (txed < len && (millis() - start < USB_TIMEOUT)) { +        txed += usbSendBytes((const uint8*)buf + txed, len - txed); +        if (old_txed != txed) {              start = millis(); -        oldstatus = status; +        } +        old_txed = txed;      }  } @@ -101,47 +77,40 @@ uint32 USBSerial::available(void) {      return usbBytesAvailable();  } -/* blocks forever until len_bytes is received */  uint32 USBSerial::read(void *buf, uint32 len) {      if (!buf) {          return 0;      } -    uint32 bytes_in = 0; -    while (len > 0) { -        uint32 new_bytes = usbReceiveBytes((uint8*)((uint8*)buf+bytes_in), len); -        len -= new_bytes; -        bytes_in += new_bytes; +    uint32 rxed = 0; +    while (rxed < len) { +        rxed += usbReceiveBytes((uint8*)buf + rxed, len - rxed);      } -    return len; +    return rxed;  } -/* blocks forever until 1 byte is received */ +/* Blocks forever until 1 byte is received */  uint8 USBSerial::read(void) { -    uint8 ch; - -    while (usbReceiveBytes(&ch, 1) == 0); -    return ch; +    uint8 buf[1]; +    this->read(buf, 1); +    return buf[0];  }  uint8 USBSerial::pending(void) {      return usbGetPending();  } -// TODO deprecate the crap out of this +uint8 USBSerial::isConnected(void) { +    return usbIsConnected() && usbIsConfigured(); +} +  uint8 USBSerial::getDTR(void) {      return usbGetDTR();  } -// TODO deprecate the crap out of this  uint8 USBSerial::getRTS(void) {      return usbGetRTS();  } -uint8 USBSerial::isConnected(void) { -    return (usbIsConnected() && usbIsConfigured()); -} -  USBSerial SerialUSB; - diff --git a/wirish/usb_serial.h b/wirish/usb_serial.h index c228837..ba9e18c 100644 --- a/wirish/usb_serial.h +++ b/wirish/usb_serial.h @@ -23,8 +23,7 @@   *****************************************************************************/  /** - * @brief wirish usb class for easy goin communication, uses libmaple's - * virtual com port implementation + * @brief Wirish virtual serial port   */  #ifndef _USB_SERIAL_H_ @@ -32,6 +31,9 @@  #include "Print.h" +/** + * @brief Virtual serial terminal. + */  class USBSerial : public Print {  public:      USBSerial(void); @@ -46,7 +48,7 @@ public:      void write(uint8);      void write(const char *str); -    void write(void *, uint32); +    void write(const void*, uint32);      uint8 getRTS();      uint8 getDTR(); diff --git a/wirish/wirish.c b/wirish/wirish.c deleted file mode 100644 index aaae9d4..0000000 --- a/wirish/wirish.c +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - *****************************************************************************/ - -/** - * @brief generic maple board bring up: - * - * By default, we bring up all maple boards running on the stm32 to 72mhz, - * clocked off the PLL, driven by the 8MHz external crystal. - * - * AHB and APB2 are clocked at 72MHz - * APB1 is clocked at 36MHz - */ - -#include "wirish.h" -#include "systick.h" -#include "gpio.h" -#include "nvic.h" -#include "usb.h" -#include "rcc.h" -#include "fsmc.h" -#include "dac.h" -#include "flash.h" - -void init(void) { -    /* make sure the flash is ready before spinning the high speed clock up */ -    flash_enable_prefetch(); -    flash_set_latency(FLASH_WAIT_STATE_2); - -#if NR_FSMC > 0 -    fsmc_native_sram_init(); -#endif - -#if NR_DAC_PINS > 0 -    dac_init(); -#endif - -    /* initialize clocks  */ -    rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9); -    rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); -    rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2); -    rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); - -    nvic_init(); -    systick_init(SYSTICK_RELOAD_VAL); -    gpio_init(); -    /* Initialize the ADC for slow conversions, to allow for high -       impedance inputs. */ -    adc_init(ADC_SMPR_55_5); -    timer_init(TIMER1, 1); -    timer_init(TIMER2, 1); -    timer_init(TIMER3, 1); -    timer_init(TIMER4, 1); -#if NR_TIMERS >= 8 -    timer_init(TIMER5, 1); -    timer_init(TIMER8, 1); -#endif -    setupUSB(); - -    /* include the board-specific init macro */ -    BOARD_INIT; -} diff --git a/wirish/wirish.h b/wirish/wirish.h index 311c74f..82a9897 100644 --- a/wirish/wirish.h +++ b/wirish/wirish.h @@ -32,25 +32,20 @@  #define _WIRISH_H_  #include "libmaple.h" + +#include "wirish_types.h"  #include "boards.h" -#include "time.h" -#include "timers.h"  #include "io.h"  #include "bits.h"  #include "pwm.h"  #include "ext_interrupts.h" +#include "wirish_debug.h"  #include "wirish_math.h" - -#ifdef __cplusplus +#include "wirish_time.h"  #include "HardwareSPI.h"  #include "HardwareSerial.h" -#include "usb_serial.h"  #include "HardwareTimer.h" -#endif - -#ifdef __cplusplus -extern "C"{ -#endif +#include "usb_serial.h"  /* Arduino wiring macros and bit defines  */  #define HIGH 0x1 @@ -74,12 +69,5 @@ extern "C"{  typedef uint8 boolean;  typedef uint8 byte; -void init(void); -void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, byte val); - -#ifdef __cplusplus -} // extern "C" -#endif -  #endif diff --git a/wirish/wirish_analog.c b/wirish/wirish_analog.cpp index 3c63342..8756caf 100644 --- a/wirish/wirish_analog.c +++ b/wirish/wirish_analog.cpp @@ -31,11 +31,12 @@  #include "io.h"  /* Assumes that the ADC has been initialized and that the pin is set - * to ANALOG_INPUT */ -uint32 analogRead(uint8 pin) { -    if(PIN_MAP[pin].adc == ADC_INVALID) { + * to INPUT_ANALOG */ +uint16 analogRead(uint8 pin) { +    const adc_dev *dev = PIN_MAP[pin].adc_device; +    if (dev == NULL) {          return 0;      } -    return adc_read(PIN_MAP[pin].adc); +    return adc_read(dev, PIN_MAP[pin].adc_channel);  } diff --git a/wirish/wirish_debug.h b/wirish/wirish_debug.h new file mode 100644 index 0000000..d4c0bab --- /dev/null +++ b/wirish/wirish_debug.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish_debug.h + * @brief High level debug port configuration + */ + +/** + * @brief Disable the JTAG and Serial Wire (SW) debug ports. + * + * You can call this function in order to use the JTAG and SW debug + * pins as ordinary GPIOs. + * + * @see enableDebugPorts() + */ +static inline void disableDebugPorts(void) { +    afio_cfg_debug_ports(AFIO_DEBUG_NONE); +} + +/** + * @brief Enable the JTAG and Serial Wire (SW) debug ports. + * + * After you call this function, the JTAG and SW debug pins will no + * longer be usable as GPIOs. + * + * @see disableDebugPorts() + */ +static inline void enableDebugPorts(void) { +    afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); +} diff --git a/wirish/wirish_digital.c b/wirish/wirish_digital.cpp index bb28f0a..9b9f175 100644 --- a/wirish/wirish_digital.c +++ b/wirish/wirish_digital.cpp @@ -30,39 +30,39 @@  #include "io.h"  void pinMode(uint8 pin, WiringPinMode mode) { -    uint8 outputMode; +    gpio_pin_mode outputMode;      boolean pwm = false; -    if (pin >= NR_GPIO_PINS) { +    if (pin >= BOARD_NR_GPIO_PINS) {          return;      }      switch(mode) {      case OUTPUT: -        outputMode = GPIO_MODE_OUTPUT_PP; +        outputMode = GPIO_OUTPUT_PP;          break;      case OUTPUT_OPEN_DRAIN: -        outputMode = GPIO_MODE_OUTPUT_OD; +        outputMode = GPIO_OUTPUT_OD;          break;      case INPUT:      case INPUT_FLOATING: -        outputMode = GPIO_MODE_INPUT_FLOATING; +        outputMode = GPIO_INPUT_FLOATING;          break;      case INPUT_ANALOG: -        outputMode = GPIO_MODE_INPUT_ANALOG; +        outputMode = GPIO_INPUT_ANALOG;          break;      case INPUT_PULLUP: -        outputMode = GPIO_MODE_INPUT_PU; +        outputMode = GPIO_INPUT_PU;          break;      case INPUT_PULLDOWN: -        outputMode = GPIO_MODE_INPUT_PD; +        outputMode = GPIO_INPUT_PD;          break;      case PWM: -        outputMode = GPIO_MODE_AF_OUTPUT_PP; +        outputMode = GPIO_AF_OUTPUT_PP;          pwm = true;          break;      case PWM_OPEN_DRAIN: -        outputMode = GPIO_MODE_AF_OUTPUT_OD; +        outputMode = GPIO_AF_OUTPUT_OD;          pwm = true;          break;      default: @@ -70,51 +70,48 @@ void pinMode(uint8 pin, WiringPinMode mode) {          return;      } -    gpio_set_mode(PIN_MAP[pin].port, PIN_MAP[pin].pin, outputMode); - -    if (PIN_MAP[pin].timer_num != TIMER_INVALID) { -        /* enable/disable timer channels if we're switching into or -           out of pwm  */ -        if (pwm) { -            timer_set_mode(PIN_MAP[pin].timer_num, -                           PIN_MAP[pin].timer_chan, -                           TIMER_PWM); -        } else { -            timer_set_mode(PIN_MAP[pin].timer_num, -                           PIN_MAP[pin].timer_chan, -                           TIMER_DISABLED); -        } +    gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); + +    if (PIN_MAP[pin].timer_device != NULL) { +        /* Enable/disable timer channels if we're switching into or +         * out of PWM. */ +        timer_set_mode(PIN_MAP[pin].timer_device, +                       PIN_MAP[pin].timer_channel, +                       pwm ? TIMER_PWM : TIMER_DISABLED);      }  }  uint32 digitalRead(uint8 pin) { -    if (pin >= NR_GPIO_PINS) { +    if (pin >= BOARD_NR_GPIO_PINS) {          return 0;      } -    return gpio_read_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin); +    return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ? +        HIGH : LOW;  }  void digitalWrite(uint8 pin, uint8 val) { -    if (pin >= NR_GPIO_PINS) { +    if (pin >= BOARD_NR_GPIO_PINS) {          return;      } -    gpio_write_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin, val); +    gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);  }  void togglePin(uint8 pin) { -    if (pin >= NR_GPIO_PINS) { +    if (pin >= BOARD_NR_GPIO_PINS) {          return;      } -     -    gpio_toggle_pin(PIN_MAP[pin].port, PIN_MAP[pin].pin); + +    gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit);  } +#define BUTTON_DEBOUNCE_DELAY 1 +  uint8 isButtonPressed() {      if (digitalRead(BOARD_BUTTON_PIN)) { -        delay(1); +        delay(BUTTON_DEBOUNCE_DELAY);          while (digitalRead(BOARD_BUTTON_PIN))              ;          return true; diff --git a/wirish/wirish_math.h b/wirish/wirish_math.h index 14614ba..f9062af 100644 --- a/wirish/wirish_math.h +++ b/wirish/wirish_math.h @@ -24,7 +24,7 @@  /**   * @file wirish_math.h - * @brief Includes cmath; provides Arduino-compatible math routines. + * @brief Includes <math.h>; provides Arduino-compatible math routines.   */  #ifndef _WIRING_MATH_H_ @@ -32,8 +32,6 @@  #include <math.h> -#ifdef __cplusplus -  /**   * @brief Initialize the pseudo-random number generator.   * @param seed the number used to initialize the seed; cannot be zero. @@ -78,8 +76,7 @@ long random(long min, long max);   * @param toEnd the end of the value's mapped range.   * @return the mapped value.   */ -/* TODO: profile code bloat due to inlining this */ -inline long map(long value, long fromStart, long fromEnd, +static inline long map(long value, long fromStart, long fromEnd,                  long toStart, long toEnd) {      return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) +          toStart; @@ -103,9 +100,7 @@ inline long map(long value, long fromStart, long fromEnd,  #ifdef abs  #undef abs  #endif -#define abs(x) (((x) > 0) ? (x) : -(unsigned)(x)) - -#endif +#define abs(x) (((x) > 0) ? (x) : -(x))  /* Following are duplicate declarations (with Doxygen comments) for   * some of the math.h functions; this is for the convenience of the diff --git a/wirish/wirish_shift.c b/wirish/wirish_shift.cpp index f67364d..f67364d 100644 --- a/wirish/wirish_shift.c +++ b/wirish/wirish_shift.cpp diff --git a/wirish/time.c b/wirish/wirish_time.cpp index c0a0649..2771e95 100644 --- a/wirish/time.c +++ b/wirish/wirish_time.cpp @@ -28,7 +28,8 @@  #include "libmaple.h"  #include "systick.h" -#include "time.h" +#include "wirish_time.h" +#include "delay.h"  void delay(unsigned long ms) {      uint32 i; @@ -38,15 +39,5 @@ void delay(unsigned long ms) {  }  void delayMicroseconds(uint32 us) { -    /* So (2^32)/12 micros max, or less than 6 minutes */ -    us *= 12; - -    /* fudge for function call overhead  */ -    us--; -    asm volatile("   mov r0, %[us]          \n\t" -                 "1: subs r0, #1            \n\t" -                 "   bhi 1b                 \n\t" -                 : -                 : [us] "r" (us) -                 : "r0"); +    delay_us(us);  } diff --git a/wirish/time.h b/wirish/wirish_time.h index 8d3d074..d5349e3 100644 --- a/wirish/time.h +++ b/wirish/wirish_time.h @@ -23,22 +23,18 @@   *****************************************************************************/  /** - * @file time.h + * @file wirish_time.h   * @brief Timing and delay functions.   */ -#ifndef _TIME_H -#define _TIME_H +#ifndef _TIME_H_ +#define _TIME_H_  #include "libmaple.h"  #include "nvic.h"  #include "systick.h"  #include "boards.h" -#ifdef __cplusplus -extern "C"{ -#endif -  #define US_PER_MS               1000  /** @@ -60,17 +56,15 @@ static inline uint32 micros(void) {      uint32 cycle_cnt;      uint32 res; -    nvic_globalirq_disable(); - -    cycle_cnt = systick_get_count(); -    ms = millis(); - -    nvic_globalirq_enable(); +    do { +        cycle_cnt = systick_get_count(); +        ms = millis(); +    } while (ms != millis());      /* SYSTICK_RELOAD_VAL is 1 less than the number of cycles it         actually takes to complete a SysTick reload */      res = (ms * US_PER_MS) + -        (SYSTICK_RELOAD_VAL + 1 - cycle_cnt)/CYCLES_PER_MICROSECOND; +        (SYSTICK_RELOAD_VAL + 1 - cycle_cnt) / CYCLES_PER_MICROSECOND;      return res;  } @@ -99,10 +93,4 @@ void delay(unsigned long ms);   */  void delayMicroseconds(uint32 us); -#ifdef __cplusplus -} // extern "C"  #endif - - -#endif - diff --git a/wirish/wirish_types.h b/wirish/wirish_types.h new file mode 100644 index 0000000..39efae0 --- /dev/null +++ b/wirish/wirish_types.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file   wirish_types.h + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief  Wirish library type definitions. + */ + +#include "libmaple_types.h" +#include "gpio.h" +#include "timer.h" +#include "adc.h" + +#ifndef _WIRISH_TYPES_H_ +#define _WIRISH_TYPES_H_ + +/** + * Invalid stm32_pin_info adc_channel value. + * @see stm32_pin_info + */ +#define ADCx 0xFF + +/** + * @brief Stores STM32-specific information related to a given Maple pin. + * @see PIN_MAP + */ +typedef struct stm32_pin_info { +    gpio_dev *gpio_device;      /**< Maple pin's GPIO device */ +    timer_dev *timer_device;    /**< Pin's timer device, if any. */ +    const adc_dev *adc_device;  /**< ADC device, if any. */ +    uint8 gpio_bit;             /**< Pin's GPIO port bit. */ +    uint8 timer_channel;        /**< Timer channel, or 0 if none. */ +    uint8 adc_channel;          /**< Pin ADC channel, or ADCx if none. */ +} stm32_pin_info; + +/** + * Variable attribute, instructs the linker to place the marked + * variable in Flash instead of RAM. */ +#define __FLASH__ __attr_flash + +#endif | 
