Initial support for STM32F4 series, based on AeroQuad codebase. Board variant for STM32F4 discovery (F407VG). Runs blinky!
This commit is contained in:
parent
db7e9ee191
commit
a5414bb548
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
|
||||
##############################################################
|
||||
discovery_f407.name=STM32 Discovery F407
|
||||
|
||||
discovery_f407.upload.tool=stlink
|
||||
discovery_f407.upload.protocol=stlink
|
||||
|
||||
#discovery_f407.upload.use_1200bps_touch=false
|
||||
discovery_f407.upload.file_type=bin
|
||||
discovery_f407.upload.ram.maximum_size=17000
|
||||
discovery_f407.upload.flash.maximum_size=108000
|
||||
discovery_f407.upload.maximum_size=108000
|
||||
|
||||
#discovery_f407.upload.usbID=1EAF:0003
|
||||
#discovery_f407.upload.altID=1
|
||||
#discovery_f407.upload.auto_reset=true
|
||||
|
||||
discovery_f407.build.mcu=cortex-m3
|
||||
discovery_f407.build.f_cpu=168000000L
|
||||
discovery_f407.build.core=maple
|
||||
discovery_f407.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -march=armv7-m -DSTM32F2 -DBOARD_discovery_f4
|
||||
discovery_f407.build.ldscript=ld/jtag.ld
|
||||
discovery_f407.build.variant=discovery_f407
|
||||
discovery_f407.build.variant_system_lib=lib_f407.a
|
||||
discovery_f407.build.vect=VECT_TAB_BASE
|
||||
discovery_f407.build.density=STM32_HIGH_DENSITY
|
||||
discovery_f407.build.error_led_port=GPIOD
|
||||
discovery_f407.build.error_led_pin=14
|
||||
#discovery_f407.build.gcc_ver=gcc-arm-none-eabi-4.8.3-2014q1
|
||||
|
||||
##############################################################
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
#include "WProgram.h"
|
||||
#endif
|
|
@ -0,0 +1,151 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "HardwareTimer.h"
|
||||
#include "boards.h" // for CYCLES_PER_MICROSECOND
|
||||
#include "wirish_math.h"
|
||||
|
||||
// TODO [0.1.0] Remove deprecated pieces
|
||||
|
||||
#ifdef STM32_MEDIUM_DENSITY
|
||||
#define NR_TIMERS 4
|
||||
#elif defined(STM32_HIGH_DENSITY)
|
||||
#define NR_TIMERS 8
|
||||
#else
|
||||
#error "Unsupported density"
|
||||
#endif
|
||||
|
||||
#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->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::resume(void) {
|
||||
timer_resume(this->dev);
|
||||
}
|
||||
|
||||
uint32 HardwareTimer::getPrescaleFactor(void) {
|
||||
return timer_get_prescaler(this->dev) + 1;
|
||||
}
|
||||
|
||||
uint32 HardwareTimer::getClockSpeed(void) {
|
||||
return rcc_dev_timer_clk_speed(this->dev->clk_id);
|
||||
}
|
||||
|
||||
void HardwareTimer::setPrescaleFactor(uint32 factor) {
|
||||
timer_set_prescaler(this->dev, (uint16)(factor - 1));
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::getOverflow() {
|
||||
return timer_get_reload(this->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::setOverflow(uint16 val) {
|
||||
timer_set_reload(this->dev, val);
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::getCount(void) {
|
||||
return timer_get_count(this->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::setCount(uint16 val) {
|
||||
uint16 ovf = this->getOverflow();
|
||||
timer_set_count(this->dev, min(val, ovf));
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::setPeriod(uint32 microseconds) {
|
||||
// Not the best way to handle this edge case?
|
||||
if (!microseconds) {
|
||||
this->setPrescaleFactor(1);
|
||||
this->setOverflow(1);
|
||||
return this->getOverflow();
|
||||
}
|
||||
|
||||
uint32 period_cyc = microseconds * CYCLES_PER_MICROSECOND;
|
||||
uint16 prescaler = (uint16)(period_cyc / MAX_RELOAD + 1);
|
||||
uint16 overflow = (uint16)round(period_cyc / prescaler);
|
||||
this->setPrescaleFactor(prescaler);
|
||||
this->setOverflow(overflow);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
void HardwareTimer::setMode(int channel, timer_mode mode) {
|
||||
timer_set_mode(this->dev, (uint8)channel, (timer_mode)mode);
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::getCompare(int channel) {
|
||||
return timer_get_compare(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
void HardwareTimer::setCompare(int channel, uint16 val) {
|
||||
uint16 ovf = this->getOverflow();
|
||||
timer_set_compare(this->dev, (uint8)channel, min(val, ovf));
|
||||
}
|
||||
|
||||
void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) {
|
||||
timer_attach_interrupt(this->dev, (uint8)channel, handler);
|
||||
}
|
||||
|
||||
void HardwareTimer::detachInterrupt(int channel) {
|
||||
timer_detach_interrupt(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
void HardwareTimer::refresh(void) {
|
||||
timer_generate_update(this->dev);
|
||||
}
|
||||
|
||||
/* -- Deprecated predefined instances -------------------------------------- */
|
||||
|
||||
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
|
|
@ -0,0 +1,337 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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 Wirish timer class.
|
||||
*/
|
||||
|
||||
#ifndef _HARDWARETIMER_H_
|
||||
#define _HARDWARETIMER_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
|
||||
|
||||
/**
|
||||
* @brief Interface to one of the 16-bit timer peripherals.
|
||||
*/
|
||||
class HardwareTimer {
|
||||
private:
|
||||
timer_dev *dev;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new HardwareTimer instance.
|
||||
* @param timerNum number of the timer to control.
|
||||
*/
|
||||
HardwareTimer(uint8 timerNum);
|
||||
|
||||
/**
|
||||
* @brief Stop the counter, without affecting its configuration.
|
||||
*
|
||||
* @see HardwareTimer::resume()
|
||||
*/
|
||||
void pause(void);
|
||||
|
||||
/**
|
||||
* @brief Resume a paused timer, without affecting its configuration.
|
||||
*
|
||||
* The timer will resume counting and firing interrupts as
|
||||
* appropriate.
|
||||
*
|
||||
* Note that there is some function call overhead associated with
|
||||
* using this method, so using it in concert with
|
||||
* HardwareTimer::pause() is not a robust way to align multiple
|
||||
* timers to the same count value.
|
||||
*
|
||||
* @see HardwareTimer::pause()
|
||||
*/
|
||||
void resume(void);
|
||||
|
||||
/**
|
||||
* @brief Get the timer's clock speed.
|
||||
* @return Timer input clock speed in Hz/second
|
||||
*/
|
||||
uint32 getClockSpeed(void);
|
||||
|
||||
/**
|
||||
* @brief Get the timer's prescale factor.
|
||||
* @return Timer prescaler, from 1 to 65,536.
|
||||
* @see HardwareTimer::setPrescaleFactor()
|
||||
*/
|
||||
uint32 getPrescaleFactor();
|
||||
|
||||
/**
|
||||
* @brief Set the timer's prescale factor.
|
||||
*
|
||||
* 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 factor The new prescale value to set, from 1 to 65,536.
|
||||
* @see HardwareTimer::refresh()
|
||||
*/
|
||||
void setPrescaleFactor(uint32 factor);
|
||||
|
||||
/**
|
||||
* @brief Get the timer overflow value.
|
||||
* @see HardwareTimer::setOverflow()
|
||||
*/
|
||||
uint16 getOverflow();
|
||||
|
||||
/**
|
||||
* @brief Set the timer overflow (or "reload") value.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @brief Get the current timer count.
|
||||
*
|
||||
* @return The timer's current count value
|
||||
*/
|
||||
uint16 getCount(void);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* overflow value.
|
||||
*/
|
||||
void setCount(uint16 val);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* @param microseconds The desired period of the timer. This must be
|
||||
* greater than zero.
|
||||
* @return The new overflow value.
|
||||
*/
|
||||
uint16 setPeriod(uint32 microseconds);
|
||||
|
||||
/**
|
||||
* @brief Configure a timer channel's mode.
|
||||
* @param channel Timer channel, from 1 to 4
|
||||
* @param mode Mode to set
|
||||
*/
|
||||
void setMode(int channel, timer_mode mode);
|
||||
|
||||
/**
|
||||
* @brief Get the compare value for the given channel.
|
||||
* @see HardwareTimer::setCompare()
|
||||
*/
|
||||
uint16 getCompare(int channel);
|
||||
|
||||
/**
|
||||
* @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 timer_mode
|
||||
* @see HardwareTimer::setMode()
|
||||
* @see HardwareTimer::attachInterrupt()
|
||||
*/
|
||||
void setCompare(int channel, uint16 compare);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @param channel the channel to attach the ISR to, from 1 to 4.
|
||||
* @param handler The ISR to attach to the given channel.
|
||||
* @see voidFuncPtr
|
||||
*/
|
||||
void attachInterrupt(int channel, voidFuncPtr handler);
|
||||
|
||||
/**
|
||||
* @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()
|
||||
*/
|
||||
void detachInterrupt(int channel);
|
||||
|
||||
/**
|
||||
* @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 refresh(void);
|
||||
|
||||
/* -- Deprecated methods ----------------------------------------------- */
|
||||
|
||||
/** @brief Deprecated; use setMode(channel, mode) instead. */
|
||||
void setChannelMode(int channel, timer_mode mode) {
|
||||
setMode(channel, mode);
|
||||
}
|
||||
|
||||
/** @brief Deprecated; use setMode(TIMER_CH1, mode) instead. */
|
||||
void setChannel1Mode(timer_mode mode) { setMode(TIMER_CH1, mode); }
|
||||
|
||||
/** @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(); }
|
||||
};
|
||||
|
||||
/* -- The rest of this file is deprecated. --------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer1;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer2;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer3;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer4;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer5;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer8;
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Print.cpp - Base class that provides print() and println()
|
||||
* Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
* Modified 23 November 2006 by David A. Mellis
|
||||
* Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com>
|
||||
*/
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
#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) {
|
||||
while (*str) {
|
||||
write(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void Print::write(const void *buffer, uint32 size) {
|
||||
uint8 *ch = (uint8*)buffer;
|
||||
while (size--) {
|
||||
write(*ch++);
|
||||
}
|
||||
}
|
||||
|
||||
void Print::print(uint8 b, int base) {
|
||||
print((uint64)b, base);
|
||||
}
|
||||
|
||||
void Print::print(char c) {
|
||||
write(c);
|
||||
}
|
||||
|
||||
void Print::print(const char str[]) {
|
||||
write(str);
|
||||
}
|
||||
|
||||
void Print::print(int n, int base) {
|
||||
print((long long)n, base);
|
||||
}
|
||||
|
||||
void Print::print(unsigned int n, int base) {
|
||||
print((unsigned long long)n, base);
|
||||
}
|
||||
|
||||
void Print::print(long n, int base) {
|
||||
print((long long)n, base);
|
||||
}
|
||||
|
||||
void Print::print(unsigned long n, int base) {
|
||||
print((unsigned long long)n, base);
|
||||
}
|
||||
|
||||
void Print::print(long long n, int base) {
|
||||
if (base == BYTE) {
|
||||
write((uint8)n);
|
||||
return;
|
||||
}
|
||||
if (n < 0) {
|
||||
print('-');
|
||||
n = -n;
|
||||
}
|
||||
printNumber(n, base);
|
||||
}
|
||||
|
||||
void Print::print(unsigned long long n, int base) {
|
||||
if (base == BYTE) {
|
||||
write((uint8)n);
|
||||
} else {
|
||||
printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
void Print::print(double n, int digits) {
|
||||
printFloat(n, digits);
|
||||
}
|
||||
|
||||
void Print::println(void) {
|
||||
print('\r');
|
||||
print('\n');
|
||||
}
|
||||
|
||||
void Print::println(char c) {
|
||||
print(c);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(const char c[]) {
|
||||
print(c);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(uint8 b, int base) {
|
||||
print(b, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(int n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(unsigned int n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(long n, int base) {
|
||||
print((long long)n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(unsigned long n, int base) {
|
||||
print((unsigned long long)n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(long long n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(unsigned long long n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void Print::println(double n, int digits) {
|
||||
print(n, digits);
|
||||
println();
|
||||
}
|
||||
|
||||
/*
|
||||
* Private methods
|
||||
*/
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Print.h - Base class that provides print() and println()
|
||||
* Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com>
|
||||
*/
|
||||
|
||||
#ifndef _PRINT_H_
|
||||
#define _PRINT_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
enum {
|
||||
BYTE = 0,
|
||||
BIN = 2,
|
||||
OCT = 8,
|
||||
DEC = 10,
|
||||
HEX = 16
|
||||
};
|
||||
|
||||
class Print {
|
||||
public:
|
||||
virtual void write(uint8 ch) = 0;
|
||||
virtual void write(const char *str);
|
||||
virtual void write(const void *buf, uint32 len);
|
||||
void print(char);
|
||||
void print(const char[]);
|
||||
void print(uint8, int=DEC);
|
||||
void print(int, int=DEC);
|
||||
void print(unsigned int, int=DEC);
|
||||
void print(long, int=DEC);
|
||||
void print(unsigned long, int=DEC);
|
||||
void print(long long, int=DEC);
|
||||
void print(unsigned long long, int=DEC);
|
||||
void print(double, int=2);
|
||||
void println(void);
|
||||
void println(char);
|
||||
void println(const char[]);
|
||||
void println(uint8, int=DEC);
|
||||
void println(int, int=DEC);
|
||||
void println(unsigned int, int=DEC);
|
||||
void println(long, int=DEC);
|
||||
void println(unsigned long, int=DEC);
|
||||
void println(long long, int=DEC);
|
||||
void println(unsigned long long, int=DEC);
|
||||
void println(double, int=2);
|
||||
private:
|
||||
void printNumber(unsigned long long, uint8);
|
||||
void printFloat(double, uint8);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "wirish.h"
|
||||
|
||||
void setup();
|
||||
void loop();
|
|
@ -0,0 +1,579 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief BIT[n] and binary literal defines, for Arduino
|
||||
* compatibility.
|
||||
*/
|
||||
|
||||
#ifndef _BIT_CONSTANTS_H_
|
||||
#define _BIT_CONSTANTS_H_
|
||||
|
||||
#define BIT0 (1 << 0)
|
||||
#define BIT1 (1 << 1)
|
||||
#define BIT2 (1 << 2)
|
||||
#define BIT3 (1 << 3)
|
||||
#define BIT4 (1 << 4)
|
||||
#define BIT5 (1 << 5)
|
||||
#define BIT6 (1 << 6)
|
||||
#define BIT7 (1 << 7)
|
||||
#define BIT8 (1 << 8)
|
||||
#define BIT9 (1 << 9)
|
||||
#define BIT10 (1 << 10)
|
||||
#define BIT11 (1 << 11)
|
||||
#define BIT12 (1 << 12)
|
||||
#define BIT13 (1 << 13)
|
||||
#define BIT14 (1 << 14)
|
||||
#define BIT15 (1 << 15)
|
||||
#define BIT16 (1 << 16)
|
||||
#define BIT17 (1 << 17)
|
||||
#define BIT18 (1 << 18)
|
||||
#define BIT19 (1 << 19)
|
||||
#define BIT20 (1 << 20)
|
||||
#define BIT21 (1 << 21)
|
||||
#define BIT22 (1 << 22)
|
||||
#define BIT23 (1 << 23)
|
||||
#define BIT24 (1 << 24)
|
||||
#define BIT25 (1 << 25)
|
||||
#define BIT26 (1 << 26)
|
||||
#define BIT27 (1 << 27)
|
||||
#define BIT28 (1 << 28)
|
||||
#define BIT29 (1 << 29)
|
||||
#define BIT30 (1 << 30)
|
||||
#define BIT31 (1 << 31)
|
||||
|
||||
#define B0 0
|
||||
#define B00 0
|
||||
#define B000 0
|
||||
#define B0000 0
|
||||
#define B00000 0
|
||||
#define B000000 0
|
||||
#define B0000000 0
|
||||
#define B00000000 0
|
||||
#define B1 1
|
||||
#define B01 1
|
||||
#define B001 1
|
||||
#define B0001 1
|
||||
#define B00001 1
|
||||
#define B000001 1
|
||||
#define B0000001 1
|
||||
#define B00000001 1
|
||||
#define B10 2
|
||||
#define B010 2
|
||||
#define B0010 2
|
||||
#define B00010 2
|
||||
#define B000010 2
|
||||
#define B0000010 2
|
||||
#define B00000010 2
|
||||
#define B11 3
|
||||
#define B011 3
|
||||
#define B0011 3
|
||||
#define B00011 3
|
||||
#define B000011 3
|
||||
#define B0000011 3
|
||||
#define B00000011 3
|
||||
#define B100 4
|
||||
#define B0100 4
|
||||
#define B00100 4
|
||||
#define B000100 4
|
||||
#define B0000100 4
|
||||
#define B00000100 4
|
||||
#define B101 5
|
||||
#define B0101 5
|
||||
#define B00101 5
|
||||
#define B000101 5
|
||||
#define B0000101 5
|
||||
#define B00000101 5
|
||||
#define B110 6
|
||||
#define B0110 6
|
||||
#define B00110 6
|
||||
#define B000110 6
|
||||
#define B0000110 6
|
||||
#define B00000110 6
|
||||
#define B111 7
|
||||
#define B0111 7
|
||||
#define B00111 7
|
||||
#define B000111 7
|
||||
#define B0000111 7
|
||||
#define B00000111 7
|
||||
#define B1000 8
|
||||
#define B01000 8
|
||||
#define B001000 8
|
||||
#define B0001000 8
|
||||
#define B00001000 8
|
||||
#define B1001 9
|
||||
#define B01001 9
|
||||
#define B001001 9
|
||||
#define B0001001 9
|
||||
#define B00001001 9
|
||||
#define B1010 10
|
||||
#define B01010 10
|
||||
#define B001010 10
|
||||
#define B0001010 10
|
||||
#define B00001010 10
|
||||
#define B1011 11
|
||||
#define B01011 11
|
||||
#define B001011 11
|
||||
#define B0001011 11
|
||||
#define B00001011 11
|
||||
#define B1100 12
|
||||
#define B01100 12
|
||||
#define B001100 12
|
||||
#define B0001100 12
|
||||
#define B00001100 12
|
||||
#define B1101 13
|
||||
#define B01101 13
|
||||
#define B001101 13
|
||||
#define B0001101 13
|
||||
#define B00001101 13
|
||||
#define B1110 14
|
||||
#define B01110 14
|
||||
#define B001110 14
|
||||
#define B0001110 14
|
||||
#define B00001110 14
|
||||
#define B1111 15
|
||||
#define B01111 15
|
||||
#define B001111 15
|
||||
#define B0001111 15
|
||||
#define B00001111 15
|
||||
#define B10000 16
|
||||
#define B010000 16
|
||||
#define B0010000 16
|
||||
#define B00010000 16
|
||||
#define B10001 17
|
||||
#define B010001 17
|
||||
#define B0010001 17
|
||||
#define B00010001 17
|
||||
#define B10010 18
|
||||
#define B010010 18
|
||||
#define B0010010 18
|
||||
#define B00010010 18
|
||||
#define B10011 19
|
||||
#define B010011 19
|
||||
#define B0010011 19
|
||||
#define B00010011 19
|
||||
#define B10100 20
|
||||
#define B010100 20
|
||||
#define B0010100 20
|
||||
#define B00010100 20
|
||||
#define B10101 21
|
||||
#define B010101 21
|
||||
#define B0010101 21
|
||||
#define B00010101 21
|
||||
#define B10110 22
|
||||
#define B010110 22
|
||||
#define B0010110 22
|
||||
#define B00010110 22
|
||||
#define B10111 23
|
||||
#define B010111 23
|
||||
#define B0010111 23
|
||||
#define B00010111 23
|
||||
#define B11000 24
|
||||
#define B011000 24
|
||||
#define B0011000 24
|
||||
#define B00011000 24
|
||||
#define B11001 25
|
||||
#define B011001 25
|
||||
#define B0011001 25
|
||||
#define B00011001 25
|
||||
#define B11010 26
|
||||
#define B011010 26
|
||||
#define B0011010 26
|
||||
#define B00011010 26
|
||||
#define B11011 27
|
||||
#define B011011 27
|
||||
#define B0011011 27
|
||||
#define B00011011 27
|
||||
#define B11100 28
|
||||
#define B011100 28
|
||||
#define B0011100 28
|
||||
#define B00011100 28
|
||||
#define B11101 29
|
||||
#define B011101 29
|
||||
#define B0011101 29
|
||||
#define B00011101 29
|
||||
#define B11110 30
|
||||
#define B011110 30
|
||||
#define B0011110 30
|
||||
#define B00011110 30
|
||||
#define B11111 31
|
||||
#define B011111 31
|
||||
#define B0011111 31
|
||||
#define B00011111 31
|
||||
#define B100000 32
|
||||
#define B0100000 32
|
||||
#define B00100000 32
|
||||
#define B100001 33
|
||||
#define B0100001 33
|
||||
#define B00100001 33
|
||||
#define B100010 34
|
||||
#define B0100010 34
|
||||
#define B00100010 34
|
||||
#define B100011 35
|
||||
#define B0100011 35
|
||||
#define B00100011 35
|
||||
#define B100100 36
|
||||
#define B0100100 36
|
||||
#define B00100100 36
|
||||
#define B100101 37
|
||||
#define B0100101 37
|
||||
#define B00100101 37
|
||||
#define B100110 38
|
||||
#define B0100110 38
|
||||
#define B00100110 38
|
||||
#define B100111 39
|
||||
#define B0100111 39
|
||||
#define B00100111 39
|
||||
#define B101000 40
|
||||
#define B0101000 40
|
||||
#define B00101000 40
|
||||
#define B101001 41
|
||||
#define B0101001 41
|
||||
#define B00101001 41
|
||||
#define B101010 42
|
||||
#define B0101010 42
|
||||
#define B00101010 42
|
||||
#define B101011 43
|
||||
#define B0101011 43
|
||||
#define B00101011 43
|
||||
#define B101100 44
|
||||
#define B0101100 44
|
||||
#define B00101100 44
|
||||
#define B101101 45
|
||||
#define B0101101 45
|
||||
#define B00101101 45
|
||||
#define B101110 46
|
||||
#define B0101110 46
|
||||
#define B00101110 46
|
||||
#define B101111 47
|
||||
#define B0101111 47
|
||||
#define B00101111 47
|
||||
#define B110000 48
|
||||
#define B0110000 48
|
||||
#define B00110000 48
|
||||
#define B110001 49
|
||||
#define B0110001 49
|
||||
#define B00110001 49
|
||||
#define B110010 50
|
||||
#define B0110010 50
|
||||
#define B00110010 50
|
||||
#define B110011 51
|
||||
#define B0110011 51
|
||||
#define B00110011 51
|
||||
#define B110100 52
|
||||
#define B0110100 52
|
||||
#define B00110100 52
|
||||
#define B110101 53
|
||||
#define B0110101 53
|
||||
#define B00110101 53
|
||||
#define B110110 54
|
||||
#define B0110110 54
|
||||
#define B00110110 54
|
||||
#define B110111 55
|
||||
#define B0110111 55
|
||||
#define B00110111 55
|
||||
#define B111000 56
|
||||
#define B0111000 56
|
||||
#define B00111000 56
|
||||
#define B111001 57
|
||||
#define B0111001 57
|
||||
#define B00111001 57
|
||||
#define B111010 58
|
||||
#define B0111010 58
|
||||
#define B00111010 58
|
||||
#define B111011 59
|
||||
#define B0111011 59
|
||||
#define B00111011 59
|
||||
#define B111100 60
|
||||
#define B0111100 60
|
||||
#define B00111100 60
|
||||
#define B111101 61
|
||||
#define B0111101 61
|
||||
#define B00111101 61
|
||||
#define B111110 62
|
||||
#define B0111110 62
|
||||
#define B00111110 62
|
||||
#define B111111 63
|
||||
#define B0111111 63
|
||||
#define B00111111 63
|
||||
#define B1000000 64
|
||||
#define B01000000 64
|
||||
#define B1000001 65
|
||||
#define B01000001 65
|
||||
#define B1000010 66
|
||||
#define B01000010 66
|
||||
#define B1000011 67
|
||||
#define B01000011 67
|
||||
#define B1000100 68
|
||||
#define B01000100 68
|
||||
#define B1000101 69
|
||||
#define B01000101 69
|
||||
#define B1000110 70
|
||||
#define B01000110 70
|
||||
#define B1000111 71
|
||||
#define B01000111 71
|
||||
#define B1001000 72
|
||||
#define B01001000 72
|
||||
#define B1001001 73
|
||||
#define B01001001 73
|
||||
#define B1001010 74
|
||||
#define B01001010 74
|
||||
#define B1001011 75
|
||||
#define B01001011 75
|
||||
#define B1001100 76
|
||||
#define B01001100 76
|
||||
#define B1001101 77
|
||||
#define B01001101 77
|
||||
#define B1001110 78
|
||||
#define B01001110 78
|
||||
#define B1001111 79
|
||||
#define B01001111 79
|
||||
#define B1010000 80
|
||||
#define B01010000 80
|
||||
#define B1010001 81
|
||||
#define B01010001 81
|
||||
#define B1010010 82
|
||||
#define B01010010 82
|
||||
#define B1010011 83
|
||||
#define B01010011 83
|
||||
#define B1010100 84
|
||||
#define B01010100 84
|
||||
#define B1010101 85
|
||||
#define B01010101 85
|
||||
#define B1010110 86
|
||||
#define B01010110 86
|
||||
#define B1010111 87
|
||||
#define B01010111 87
|
||||
#define B1011000 88
|
||||
#define B01011000 88
|
||||
#define B1011001 89
|
||||
#define B01011001 89
|
||||
#define B1011010 90
|
||||
#define B01011010 90
|
||||
#define B1011011 91
|
||||
#define B01011011 91
|
||||
#define B1011100 92
|
||||
#define B01011100 92
|
||||
#define B1011101 93
|
||||
#define B01011101 93
|
||||
#define B1011110 94
|
||||
#define B01011110 94
|
||||
#define B1011111 95
|
||||
#define B01011111 95
|
||||
#define B1100000 96
|
||||
#define B01100000 96
|
||||
#define B1100001 97
|
||||
#define B01100001 97
|
||||
#define B1100010 98
|
||||
#define B01100010 98
|
||||
#define B1100011 99
|
||||
#define B01100011 99
|
||||
#define B1100100 100
|
||||
#define B01100100 100
|
||||
#define B1100101 101
|
||||
#define B01100101 101
|
||||
#define B1100110 102
|
||||
#define B01100110 102
|
||||
#define B1100111 103
|
||||
#define B01100111 103
|
||||
#define B1101000 104
|
||||
#define B01101000 104
|
||||
#define B1101001 105
|
||||
#define B01101001 105
|
||||
#define B1101010 106
|
||||
#define B01101010 106
|
||||
#define B1101011 107
|
||||
#define B01101011 107
|
||||
#define B1101100 108
|
||||
#define B01101100 108
|
||||
#define B1101101 109
|
||||
#define B01101101 109
|
||||
#define B1101110 110
|
||||
#define B01101110 110
|
||||
#define B1101111 111
|
||||
#define B01101111 111
|
||||
#define B1110000 112
|
||||
#define B01110000 112
|
||||
#define B1110001 113
|
||||
#define B01110001 113
|
||||
#define B1110010 114
|
||||
#define B01110010 114
|
||||
#define B1110011 115
|
||||
#define B01110011 115
|
||||
#define B1110100 116
|
||||
#define B01110100 116
|
||||
#define B1110101 117
|
||||
#define B01110101 117
|
||||
#define B1110110 118
|
||||
#define B01110110 118
|
||||
#define B1110111 119
|
||||
#define B01110111 119
|
||||
#define B1111000 120
|
||||
#define B01111000 120
|
||||
#define B1111001 121
|
||||
#define B01111001 121
|
||||
#define B1111010 122
|
||||
#define B01111010 122
|
||||
#define B1111011 123
|
||||
#define B01111011 123
|
||||
#define B1111100 124
|
||||
#define B01111100 124
|
||||
#define B1111101 125
|
||||
#define B01111101 125
|
||||
#define B1111110 126
|
||||
#define B01111110 126
|
||||
#define B1111111 127
|
||||
#define B01111111 127
|
||||
#define B10000000 128
|
||||
#define B10000001 129
|
||||
#define B10000010 130
|
||||
#define B10000011 131
|
||||
#define B10000100 132
|
||||
#define B10000101 133
|
||||
#define B10000110 134
|
||||
#define B10000111 135
|
||||
#define B10001000 136
|
||||
#define B10001001 137
|
||||
#define B10001010 138
|
||||
#define B10001011 139
|
||||
#define B10001100 140
|
||||
#define B10001101 141
|
||||
#define B10001110 142
|
||||
#define B10001111 143
|
||||
#define B10010000 144
|
||||
#define B10010001 145
|
||||
#define B10010010 146
|
||||
#define B10010011 147
|
||||
#define B10010100 148
|
||||
#define B10010101 149
|
||||
#define B10010110 150
|
||||
#define B10010111 151
|
||||
#define B10011000 152
|
||||
#define B10011001 153
|
||||
#define B10011010 154
|
||||
#define B10011011 155
|
||||
#define B10011100 156
|
||||
#define B10011101 157
|
||||
#define B10011110 158
|
||||
#define B10011111 159
|
||||
#define B10100000 160
|
||||
#define B10100001 161
|
||||
#define B10100010 162
|
||||
#define B10100011 163
|
||||
#define B10100100 164
|
||||
#define B10100101 165
|
||||
#define B10100110 166
|
||||
#define B10100111 167
|
||||
#define B10101000 168
|
||||
#define B10101001 169
|
||||
#define B10101010 170
|
||||
#define B10101011 171
|
||||
#define B10101100 172
|
||||
#define B10101101 173
|
||||
#define B10101110 174
|
||||
#define B10101111 175
|
||||
#define B10110000 176
|
||||
#define B10110001 177
|
||||
#define B10110010 178
|
||||
#define B10110011 179
|
||||
#define B10110100 180
|
||||
#define B10110101 181
|
||||
#define B10110110 182
|
||||
#define B10110111 183
|
||||
#define B10111000 184
|
||||
#define B10111001 185
|
||||
#define B10111010 186
|
||||
#define B10111011 187
|
||||
#define B10111100 188
|
||||
#define B10111101 189
|
||||
#define B10111110 190
|
||||
#define B10111111 191
|
||||
#define B11000000 192
|
||||
#define B11000001 193
|
||||
#define B11000010 194
|
||||
#define B11000011 195
|
||||
#define B11000100 196
|
||||
#define B11000101 197
|
||||
#define B11000110 198
|
||||
#define B11000111 199
|
||||
#define B11001000 200
|
||||
#define B11001001 201
|
||||
#define B11001010 202
|
||||
#define B11001011 203
|
||||
#define B11001100 204
|
||||
#define B11001101 205
|
||||
#define B11001110 206
|
||||
#define B11001111 207
|
||||
#define B11010000 208
|
||||
#define B11010001 209
|
||||
#define B11010010 210
|
||||
#define B11010011 211
|
||||
#define B11010100 212
|
||||
#define B11010101 213
|
||||
#define B11010110 214
|
||||
#define B11010111 215
|
||||
#define B11011000 216
|
||||
#define B11011001 217
|
||||
#define B11011010 218
|
||||
#define B11011011 219
|
||||
#define B11011100 220
|
||||
#define B11011101 221
|
||||
#define B11011110 222
|
||||
#define B11011111 223
|
||||
#define B11100000 224
|
||||
#define B11100001 225
|
||||
#define B11100010 226
|
||||
#define B11100011 227
|
||||
#define B11100100 228
|
||||
#define B11100101 229
|
||||
#define B11100110 230
|
||||
#define B11100111 231
|
||||
#define B11101000 232
|
||||
#define B11101001 233
|
||||
#define B11101010 234
|
||||
#define B11101011 235
|
||||
#define B11101100 236
|
||||
#define B11101101 237
|
||||
#define B11101110 238
|
||||
#define B11101111 239
|
||||
#define B11110000 240
|
||||
#define B11110001 241
|
||||
#define B11110010 242
|
||||
#define B11110011 243
|
||||
#define B11110100 244
|
||||
#define B11110101 245
|
||||
#define B11110110 246
|
||||
#define B11110111 247
|
||||
#define B11111000 248
|
||||
#define B11111001 249
|
||||
#define B11111010 250
|
||||
#define B11111011 251
|
||||
#define B11111100 252
|
||||
#define B11111101 253
|
||||
#define B11111110 254
|
||||
#define B11111111 255
|
||||
|
||||
#endif /* _BIT_CONSTANTS_H_ */
|
|
@ -0,0 +1,30 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Note: Use of this header file is deprecated. Use bit_constants.h
|
||||
instead. */
|
||||
|
||||
#include "bit_constants.h"
|
|
@ -0,0 +1,180 @@
|
|||
/******************************************************************************
|
||||
* 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"
|
||||
#ifdef STM32F2
|
||||
//#include "usbF4.h"
|
||||
#endif
|
||||
|
||||
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();
|
||||
|
||||
#ifdef STM32F2
|
||||
rcc_clk_enable(RCC_SYSCFG);
|
||||
#else
|
||||
afio_init();
|
||||
#endif
|
||||
|
||||
boardInit();
|
||||
setupADC();
|
||||
setupTimers();
|
||||
|
||||
//setupUSB();
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
#ifndef STM32F2
|
||||
// for F2 and F4 CPUs this is done in SetupClock...(), e.g. in SetupClock168MHz()
|
||||
flash_enable_prefetch();
|
||||
flash_set_latency(FLASH_WAIT_STATE_2);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 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() {
|
||||
#ifdef STM32F2
|
||||
setupADC_F2();
|
||||
#else
|
||||
rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6);
|
||||
#endif
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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 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_
|
||||
#define _BOARDS_H_
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "gpio.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "wirish_types.h"
|
||||
|
||||
/* 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,
|
||||
D32, D33, D34, D35, D36, D37, D38, D39, D40, D41, D42, D43, D44, D45, D46,
|
||||
D47, D48, D49, D50, D51, D52, D53, D54, D55, D56, D57, D58, D59, D60, D61,
|
||||
D62, D63, D64, D65, D66, D67, D68, D69, D70, D71, D72, D73, D74, D75, D76,
|
||||
D77, D78, D79, D80, D81, D82, D83, D84, D85, D86, D87, D88, D89, D90, D91,
|
||||
D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105,
|
||||
D106, D107, D108, D109, D110, D111, };
|
||||
|
||||
/**
|
||||
* @brief Maps each Maple pin to a corresponding stm32_pin_info.
|
||||
* @see stm32_pin_info
|
||||
*/
|
||||
extern const stm32_pin_info PIN_MAP[];
|
||||
|
||||
/**
|
||||
* @brief Pins capable of PWM output.
|
||||
*
|
||||
* Its length is BOARD_NR_PWM_PINS.
|
||||
*/
|
||||
extern const uint8 boardPWMPins[];
|
||||
|
||||
/**
|
||||
* @brief Array of pins capable of analog input.
|
||||
*
|
||||
* Its length is BOARD_NR_ADC_PINS.
|
||||
*/
|
||||
extern const uint8 boardADCPins[];
|
||||
|
||||
/**
|
||||
* @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[];
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/* Include the appropriate private header from boards/: */
|
||||
|
||||
/* FIXME HACK put boards/ before these paths once IDE uses make. */
|
||||
|
||||
#ifdef BOARD_maple
|
||||
#include "maple.h"
|
||||
#elif defined(BOARD_maple_native)
|
||||
#include "maple_native.h"
|
||||
#elif defined(BOARD_maple_mini)
|
||||
#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"
|
||||
#elif defined(BOARD_aeroquad32) || defined(BOARD_aeroquad32f1)
|
||||
#include "aeroquad32.h"
|
||||
#elif defined(BOARD_aeroquad32mini)
|
||||
#include "aeroquad32mini.h"
|
||||
#elif defined(BOARD_discovery_f4)
|
||||
#include "discovery_f4.h"
|
||||
#elif defined(BOARD_freeflight)
|
||||
#include "freeflight.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
|
||||
|
||||
/* Set derived definitions */
|
||||
|
||||
#define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND
|
||||
#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,6 @@
|
|||
/* We compile with nodefaultlibs, so we need to provide an error
|
||||
* handler for an empty pure virtual function */
|
||||
extern "C" void __cxa_pure_virtual(void) {
|
||||
while(1)
|
||||
;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file ext_interrupts.c
|
||||
*
|
||||
* @brief Wiring-like interface for external interrupts
|
||||
*/
|
||||
|
||||
#include "boards.h"
|
||||
#include "gpio.h"
|
||||
#include "exti.h"
|
||||
#include "ext_interrupts.h"
|
||||
|
||||
static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode);
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
exti_trigger_mode outMode = exti_out_mode(mode);
|
||||
|
||||
exti_attach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit),
|
||||
gpio_exti_port(PIN_MAP[pin].gpio_device),
|
||||
handler,
|
||||
outMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable any external interrupt attached to a pin.
|
||||
* @param pin Pin number to detach any interrupt from.
|
||||
*/
|
||||
void detachInterrupt(uint8 pin) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/**
|
||||
* @file ext_interrupts.h
|
||||
*
|
||||
* @brief Wiring-like external interrupt prototypes and types.
|
||||
*/
|
||||
|
||||
#ifndef _EXT_INTERRUPTS_H_
|
||||
#define _EXT_INTERRUPTS_H_
|
||||
|
||||
/**
|
||||
* The kind of transition on an external pin which should trigger an
|
||||
* interrupt.
|
||||
*/
|
||||
typedef enum ExtIntTriggerMode {
|
||||
RISING, /**< To trigger an interrupt when the pin transitions LOW
|
||||
to HIGH */
|
||||
FALLING, /**< To trigger an interrupt when the pin transitions
|
||||
HIGH to LOW */
|
||||
CHANGE /**< To trigger an interrupt when the pin transitions from
|
||||
LOW to HIGH or HIGH to LOW (i.e., when the pin
|
||||
changes). */
|
||||
} ExtIntTriggerMode;
|
||||
|
||||
/**
|
||||
* @brief Registers an interrupt handler on a pin.
|
||||
*
|
||||
* The interrupt will be triggered on a given transition on the pin,
|
||||
* as specified by the mode parameter. The handler runs in interrupt
|
||||
* context. The new handler will replace whatever handler is
|
||||
* currently registered for the pin, if any.
|
||||
*
|
||||
* @param pin Maple pin number
|
||||
* @param handler Function to run upon external interrupt trigger.
|
||||
* The handler should take no arguments, and have void return type.
|
||||
* @param mode Type of transition to trigger on, e.g. falling, rising, etc.
|
||||
*
|
||||
* @sideeffect Registers a handler
|
||||
* @see detachInterrupt()
|
||||
*/
|
||||
void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode);
|
||||
|
||||
/**
|
||||
* @brief Disable any registered external interrupt.
|
||||
* @param pin Maple pin number
|
||||
* @sideeffect unregisters external interrupt handler
|
||||
* @see attachInterrupt()
|
||||
*/
|
||||
void detachInterrupt(uint8 pin);
|
||||
|
||||
/**
|
||||
* Re-enable interrupts.
|
||||
*
|
||||
* Call this after noInterrupts() to re-enable interrupt handling,
|
||||
* after you have finished with a timing-critical section of code.
|
||||
*
|
||||
* @see noInterrupts()
|
||||
*/
|
||||
static inline void interrupts() {
|
||||
nvic_globalirq_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable interrupts.
|
||||
*
|
||||
* After calling this function, all user-programmable interrupts will
|
||||
* be disabled. You can call this function before a timing-critical
|
||||
* section of code, then call interrupts() to re-enable interrupt
|
||||
* handling.
|
||||
*
|
||||
* @see interrupts()
|
||||
*/
|
||||
static inline void noInterrupts() {
|
||||
nvic_globalirq_disable();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file io.h
|
||||
*
|
||||
* @brief Arduino-compatible digital pin I/O interface.
|
||||
*/
|
||||
|
||||
#ifndef _IO_H_
|
||||
#define _IO_H_
|
||||
|
||||
#include "gpio.h"
|
||||
#include "adc.h"
|
||||
|
||||
#include "wirish_time.h"
|
||||
|
||||
/**
|
||||
* Specifies a GPIO pin behavior.
|
||||
* @see pinMode()
|
||||
*/
|
||||
typedef enum WiringPinMode {
|
||||
OUTPUT, /**< Basic digital output: when the pin is HIGH, the
|
||||
voltage is held at +3.3v (Vcc) and when it is LOW, it
|
||||
is pulled down to ground. */
|
||||
|
||||
OUTPUT_OPEN_DRAIN, /**< In open drain mode, the pin indicates
|
||||
"low" by accepting current flow to ground
|
||||
and "high" by providing increased
|
||||
impedance. An example use would be to
|
||||
connect a pin to a bus line (which is pulled
|
||||
up to a positive voltage by a separate
|
||||
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
|
||||
"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
|
||||
from the pin. */
|
||||
|
||||
INPUT, /**< Basic digital input. The pin voltage is sampled; when
|
||||
it is closer to 3.3v (Vcc) the pin status is high, and
|
||||
when it is closer to 0v (ground) it is low. If no
|
||||
external circuit is pulling the pin voltage to high or
|
||||
low, it will tend to randomly oscillate and be very
|
||||
sensitive to noise (e.g., a breath of air across the pin
|
||||
might cause the state to flip). */
|
||||
|
||||
INPUT_ANALOG, /**< This is a special mode for when the pin will be
|
||||
used for analog (not digital) reads. Enables ADC
|
||||
conversion to be performed on the voltage at the
|
||||
pin. */
|
||||
|
||||
INPUT_PULLUP, /**< The state of the pin in this mode is reported
|
||||
the same way as with INPUT, but the pin voltage
|
||||
is gently "pulled up" towards +3.3v. This means
|
||||
the state will be high unless an external device
|
||||
is specifically pulling the pin down to ground,
|
||||
in which case the "gentle" pull-up will not
|
||||
affect the state of the input. */
|
||||
|
||||
INPUT_PULLDOWN, /**< The state of the pin in this mode is reported
|
||||
the same way as with INPUT, but the pin voltage
|
||||
is gently "pulled down" towards 0v. This means
|
||||
the state will be low unless an external device
|
||||
is specifically pulling the pin up to 3.3v, in
|
||||
which case the "gentle" pull-down will not
|
||||
affect the state of the input. */
|
||||
|
||||
INPUT_FLOATING, /**< Synonym for INPUT. */
|
||||
|
||||
PWM, /**< This is a special mode for when the pin will be used for
|
||||
PWM output (a special case of digital output). */
|
||||
|
||||
PWM_OPEN_DRAIN, /**< Like PWM, except that instead of alternating
|
||||
cycles of LOW and HIGH, the voltage on the pin
|
||||
consists of alternating cycles of LOW and
|
||||
floating (disconnected). */
|
||||
} WiringPinMode;
|
||||
|
||||
/**
|
||||
* Configure behavior of a GPIO pin.
|
||||
*
|
||||
* @param pin Number of pin to configure.
|
||||
* @param mode Mode corresponding to desired pin behavior.
|
||||
* @see WiringPinMode
|
||||
*/
|
||||
void pinMode(uint8 pin, WiringPinMode mode);
|
||||
|
||||
/**
|
||||
* Writes a (digital) value to a pin. The pin must have its
|
||||
* mode set to OUTPUT or OUTPUT_OPEN_DRAIN.
|
||||
*
|
||||
* @param pin Pin to write to.
|
||||
* @param value Either LOW (write a 0) or HIGH (write a 1).
|
||||
* @see pinMode()
|
||||
*/
|
||||
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.
|
||||
* @return LOW or HIGH.
|
||||
* @see pinMode()
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param pin Pin to read from.
|
||||
* @return Converted voltage, in the range 0--4095, (i.e. a 12-bit ADC
|
||||
* conversion).
|
||||
* @see pinMode()
|
||||
*/
|
||||
uint16 analogRead(uint8 pin);
|
||||
|
||||
/**
|
||||
* Toggles the digital value at the given pin.
|
||||
*
|
||||
* The pin must have its mode set to OUTPUT.
|
||||
*
|
||||
* @param pin the pin to toggle. If the pin is HIGH, set it LOW. If
|
||||
* it is LOW, set it HIGH.
|
||||
*
|
||||
* @see pinMode()
|
||||
*/
|
||||
void togglePin(uint8 pin);
|
||||
|
||||
/**
|
||||
* Toggle the LED.
|
||||
*
|
||||
* If the LED is on, turn it off. If it is off, turn it on.
|
||||
*
|
||||
* The LED must its mode set to OUTPUT. This can be accomplished
|
||||
* portably over all LeafLabs boards by calling pinMode(BOARD_LED_PIN,
|
||||
* OUTPUT) before calling this function.
|
||||
*
|
||||
* @see pinMode()
|
||||
*/
|
||||
static inline void toggleLED() {
|
||||
togglePin(BOARD_LED_PIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the button is currently pressed, waits until the button is no
|
||||
* longer being pressed, and returns true. Otherwise, returns false.
|
||||
*
|
||||
* The button pin must have its mode set to INPUT. This can be
|
||||
* accomplished portably over all LeafLabs boards by calling
|
||||
* pinMode(BOARD_BUTTON_PIN, INPUT).
|
||||
*
|
||||
* @see pinMode()
|
||||
*/
|
||||
uint8 isButtonPressed();
|
||||
|
||||
/**
|
||||
* Wait until the button is pressed and released, timing out if no
|
||||
* press occurs.
|
||||
*
|
||||
* The button pin must have its mode set to INPUT. This can be
|
||||
* accomplished portably over all LeafLabs boards by calling
|
||||
* pinMode(BOARD_BUTTON_PIN, INPUT).
|
||||
*
|
||||
* @param timeout_millis Number of milliseconds to wait until the
|
||||
* 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=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);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,427 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Wirish SPI implementation.
|
||||
*/
|
||||
|
||||
#include "HardwareSPI.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
#include "rcc.h"
|
||||
|
||||
#include "wirish.h"
|
||||
#include "boards.h"
|
||||
|
||||
struct spi_pins {
|
||||
uint8 nss;
|
||||
uint8 sck;
|
||||
uint8 miso;
|
||||
uint8 mosi;
|
||||
};
|
||||
|
||||
static const spi_pins* dev_to_spi_pins(spi_dev *dev);
|
||||
|
||||
static void enable_device(spi_dev *dev,
|
||||
bool as_master,
|
||||
SPIFrequency frequency,
|
||||
spi_cfg_flag endianness,
|
||||
spi_mode mode);
|
||||
|
||||
static const spi_pins board_spi_pins[] __FLASH__ = {
|
||||
{BOARD_SPI1_NSS_PIN,
|
||||
BOARD_SPI1_SCK_PIN,
|
||||
BOARD_SPI1_MISO_PIN,
|
||||
BOARD_SPI1_MOSI_PIN},
|
||||
#ifdef BOARD_SPI2_NSS_PIN
|
||||
{BOARD_SPI2_NSS_PIN,
|
||||
BOARD_SPI2_SCK_PIN,
|
||||
BOARD_SPI2_MISO_PIN,
|
||||
BOARD_SPI2_MOSI_PIN},
|
||||
#endif
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
{BOARD_SPI3_NSS_PIN,
|
||||
BOARD_SPI3_SCK_PIN,
|
||||
BOARD_SPI3_MISO_PIN,
|
||||
BOARD_SPI3_MOSI_PIN},
|
||||
#endif
|
||||
#ifdef STM32F2
|
||||
{BOARD_SPI3B_NSS_PIN,
|
||||
BOARD_SPI3B_SCK_PIN,
|
||||
BOARD_SPI3B_MISO_PIN,
|
||||
BOARD_SPI3B_MOSI_PIN},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
|
||||
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
|
||||
#ifdef STM32F2
|
||||
case 4:
|
||||
this->spi_d = SPI4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up/tear down
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void HardwareSPI::begin(void) {
|
||||
this->begin(SPI_1_125MHZ, MSBFIRST, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void HardwareSPI::beginSlave(void) {
|
||||
this->beginSlave(MSBFIRST, 0);
|
||||
}
|
||||
|
||||
void HardwareSPI::end(void) {
|
||||
if (!spi_is_enabled(this->spi_d)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O
|
||||
*/
|
||||
|
||||
uint8 HardwareSPI::read(void) {
|
||||
uint8 buf[1];
|
||||
this->read(buf, 1);
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void HardwareSPI::readMaster(uint8 *buf, uint32 len) {
|
||||
uint32 rxed = 0;
|
||||
while (rxed < len) {
|
||||
spi_tx_reg(this->spi_d, 0xff);
|
||||
while (!spi_is_rx_nonempty(this->spi_d))
|
||||
;
|
||||
buf[rxed++] = (uint8)spi_rx_reg(this->spi_d);
|
||||
buf[rxed++] = this->spi_d->regs->DR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void HardwareSPI::readMaster(uint8 *buf, uint32 len) {
|
||||
spi_reg_map *r = this->spi_d->regs;
|
||||
uint32 rxed = 0;
|
||||
while (rxed < len) {
|
||||
r->DR = 0xff;
|
||||
while (!(r->SR & SPI_SR_RXNE))
|
||||
;
|
||||
buf[rxed++] = r->DR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HardwareSPI::waitReady() {
|
||||
while (!spi_is_rx_nonempty(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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Pin accessors
|
||||
*/
|
||||
|
||||
uint8 HardwareSPI::misoPin(void) {
|
||||
return dev_to_spi_pins(this->spi_d)->miso;
|
||||
}
|
||||
|
||||
uint8 HardwareSPI::mosiPin(void) {
|
||||
return dev_to_spi_pins(this->spi_d)->mosi;
|
||||
}
|
||||
|
||||
uint8 HardwareSPI::sckPin(void) {
|
||||
return dev_to_spi_pins(this->spi_d)->sck;
|
||||
}
|
||||
|
||||
uint8 HardwareSPI::nssPin(void) {
|
||||
return dev_to_spi_pins(this->spi_d)->nss;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deprecated functions
|
||||
*/
|
||||
|
||||
uint8 HardwareSPI::send(uint8 data) {
|
||||
uint8 buf[] = {data};
|
||||
return this->send(buf, 1);
|
||||
}
|
||||
|
||||
#if 1
|
||||
uint8 HardwareSPI::send(const uint8 *buf, uint32 len) {
|
||||
uint32 txed = 0;
|
||||
uint8 ret = 0;
|
||||
while (txed < len) {
|
||||
this->write(buf[txed++]);
|
||||
ret = this->read();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
// this does not work for an unknown reason
|
||||
uint8 HardwareSPI::send(const uint8 *buf, uint32 len) {
|
||||
volatile uint32 *dr = &(this->spi_d->regs->DR);
|
||||
volatile uint32 *sr = &(this->spi_d->regs->SR);
|
||||
uint32 txed = 0;
|
||||
uint32 rx=0;
|
||||
while (txed < len) {
|
||||
//while (!(*sr & SPI_SR_TXE))
|
||||
// ;
|
||||
//*dr = buf[txed++];
|
||||
this->write(buf[txed++]);
|
||||
|
||||
while (!(*sr & SPI_SR_RXNE))
|
||||
;
|
||||
rx = *dr;
|
||||
//rx = this->read();
|
||||
}
|
||||
|
||||
return rx;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8 HardwareSPI::recv(void) {
|
||||
return this->read();
|
||||
}
|
||||
|
||||
/*
|
||||
* Auxiliary functions
|
||||
*/
|
||||
|
||||
static void configure_gpios(spi_dev *dev, bool as_master);
|
||||
static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq);
|
||||
|
||||
static const spi_pins* dev_to_spi_pins(spi_dev *dev) {
|
||||
switch (dev->clk_id) {
|
||||
case RCC_SPI1: return board_spi_pins;
|
||||
case RCC_SPI2: return board_spi_pins + 1;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
case RCC_SPI3: return board_spi_pins + 2;
|
||||
#endif
|
||||
#ifdef STM32F2
|
||||
case RCC_SPI4: return board_spi_pins + 3;
|
||||
#endif
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_gpios(spi_dev *dev, bool as_master) {
|
||||
const spi_pins *pins = dev_to_spi_pins(dev);
|
||||
|
||||
if (!pins) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stm32_pin_info *nssi = (pins->nss >= 0) ? &PIN_MAP[pins->nss] : NULL;
|
||||
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];
|
||||
|
||||
if(nssi) {
|
||||
disable_pwm(nssi);
|
||||
}
|
||||
disable_pwm(scki);
|
||||
disable_pwm(misoi);
|
||||
disable_pwm(mosii);
|
||||
|
||||
#ifdef STM32F2
|
||||
if(dev->clk_id <= RCC_SPI2) {
|
||||
if(nssi) {
|
||||
if(!as_master) {
|
||||
gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 5);
|
||||
}
|
||||
}
|
||||
gpio_set_af_mode(scki->gpio_device, scki->gpio_bit, 5);
|
||||
gpio_set_af_mode(misoi->gpio_device, misoi->gpio_bit, 5);
|
||||
gpio_set_af_mode(mosii->gpio_device, mosii->gpio_bit, 5);
|
||||
//gpio_set_af_mode(GPIOC, 10, 6);
|
||||
//gpio_set_af_mode(GPIOC, 11, 6);
|
||||
//gpio_set_af_mode(GPIOC, 12, 6);
|
||||
} else {
|
||||
if(nssi) {
|
||||
if(!as_master) {
|
||||
gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 6);
|
||||
}
|
||||
}
|
||||
gpio_set_af_mode(scki->gpio_device, scki->gpio_bit, 6);
|
||||
gpio_set_af_mode(misoi->gpio_device, misoi->gpio_bit, 6);
|
||||
gpio_set_af_mode(mosii->gpio_device, mosii->gpio_bit, 6);
|
||||
//gpio_set_af_mode(GPIOC, 10, 6);
|
||||
//gpio_set_af_mode(GPIOC, 11, 6);
|
||||
//gpio_set_af_mode(GPIOC, 12, 6);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(nssi) {
|
||||
spi_gpio_cfg(as_master,
|
||||
nssi->gpio_device,
|
||||
nssi->gpio_bit,
|
||||
scki->gpio_device,
|
||||
scki->gpio_bit,
|
||||
misoi->gpio_bit,
|
||||
mosii->gpio_bit);
|
||||
} else {
|
||||
spi_gpio_cfg(as_master,
|
||||
NULL,
|
||||
-1,
|
||||
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]);
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @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_
|
||||
|
||||
/**
|
||||
* @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_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 */
|
||||
} SPIFrequency;
|
||||
|
||||
#define MAX_SPI_FREQS 8
|
||||
|
||||
#if CYCLES_PER_MICROSECOND != 72
|
||||
/* TODO [0.2.0?] something smarter than this */
|
||||
//#warning "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 {
|
||||
public:
|
||||
/**
|
||||
* @param spiPortNumber Number of the SPI port to manage.
|
||||
*/
|
||||
HardwareSPI(uint32 spiPortNumber);
|
||||
|
||||
/*
|
||||
* Set up/tear down
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
|
||||
*/
|
||||
void begin(void);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/*
|
||||
* I/O
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 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 readMaster(uint8 *buffer, uint32 length);
|
||||
|
||||
|
||||
void waitReady();
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/*
|
||||
* Pin accessors
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the number of the MISO (master in, slave out) pin
|
||||
*/
|
||||
uint8 misoPin(void);
|
||||
|
||||
/**
|
||||
* @brief Return the number of the MOSI (master out, slave in) pin
|
||||
*/
|
||||
uint8 mosiPin(void);
|
||||
|
||||
/**
|
||||
* @brief Return the number of the SCK (serial clock) pin
|
||||
*/
|
||||
uint8 sckPin(void);
|
||||
|
||||
/**
|
||||
* @brief Return the number of the NSS (slave select) pin
|
||||
*/
|
||||
uint8 nssPin(void);
|
||||
|
||||
/* -- 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(const uint8 *data, uint32 length);
|
||||
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Use HardwareSPI::read() instead.
|
||||
*
|
||||
* @see HardwareSPI::read()
|
||||
*/
|
||||
uint8 recv(void);
|
||||
private:
|
||||
spi_dev *spi_d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file HardwareSerial.cpp
|
||||
* @brief Wirish serial port implementation.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "gpio.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
#include "boards.h"
|
||||
|
||||
#define TX1 BOARD_USART1_TX_PIN
|
||||
#define RX1 BOARD_USART1_RX_PIN
|
||||
|
||||
#ifdef BOARD_USART2_TX_PIN
|
||||
#define TX2 BOARD_USART2_TX_PIN
|
||||
#define RX2 BOARD_USART2_RX_PIN
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_USART3_TX_PIN
|
||||
#define TX3 BOARD_USART3_TX_PIN
|
||||
#define RX3 BOARD_USART3_RX_PIN
|
||||
#endif
|
||||
|
||||
#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 Serial1(USART1, TX1, RX1);
|
||||
|
||||
#ifdef TX2
|
||||
HardwareSerial Serial2(USART2, TX2, RX2);
|
||||
#endif
|
||||
|
||||
#ifdef TX3
|
||||
HardwareSerial Serial3(USART3, TX3, RX3);
|
||||
#endif
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6)
|
||||
HardwareSerial Serial4(UART4, TX4, RX4);
|
||||
HardwareSerial Serial5(UART5, TX5, RX5);
|
||||
#endif
|
||||
|
||||
HardwareSerial::HardwareSerial(usart_dev *usart_device,
|
||||
uint8 tx_pin,
|
||||
uint8 rx_pin) {
|
||||
this->usart_device = usart_device;
|
||||
this->tx_pin = tx_pin;
|
||||
this->rx_pin = rx_pin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up/tear down
|
||||
*/
|
||||
|
||||
void HardwareSerial::begin(uint32 baud) {
|
||||
ASSERT(baud <= usart_device->max_baud);
|
||||
|
||||
if (baud > usart_device->max_baud) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stm32_pin_info *txi = &PIN_MAP[tx_pin];
|
||||
const stm32_pin_info *rxi = &PIN_MAP[rx_pin];
|
||||
#ifdef STM32F2
|
||||
// int af = 7<<8;
|
||||
gpio_set_af_mode(txi->gpio_device, txi->gpio_bit, 7);
|
||||
gpio_set_af_mode(rxi->gpio_device, rxi->gpio_bit, 7);
|
||||
gpio_set_mode(txi->gpio_device, txi->gpio_bit, (gpio_pin_mode)(GPIO_AF_OUTPUT_PP | GPIO_PUPD_INPUT_PU | 0x700));
|
||||
gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, (gpio_pin_mode)(GPIO_MODE_AF | GPIO_PUPD_INPUT_PU | 0x700));
|
||||
//gpio_set_mode(txi->gpio_device, txi->gpio_bit, (gpio_pin_mode)(GPIO_PUPD_INPUT_PU));
|
||||
//gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, (gpio_pin_mode)(GPIO_PUPD_INPUT_PU));
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
#if 0
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
usart_init(usart_device);
|
||||
usart_set_baud_rate(usart_device, baud);
|
||||
usart_enable(usart_device);
|
||||
}
|
||||
|
||||
void HardwareSerial::end(void) {
|
||||
usart_disable(usart_device);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O
|
||||
*/
|
||||
|
||||
int HardwareSerial::read(void) {
|
||||
if(usart_data_available(usart_device) > 0) {
|
||||
return usart_getc(usart_device);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 HardwareSerial::available(void) {
|
||||
return usart_data_available(usart_device);
|
||||
}
|
||||
|
||||
uint32 HardwareSerial::pending(void) {
|
||||
return usart_data_pending(usart_device);
|
||||
}
|
||||
|
||||
void HardwareSerial::write(unsigned char ch) {
|
||||
usart_putc(usart_device, ch);
|
||||
}
|
||||
|
||||
void HardwareSerial::flush(void) {
|
||||
usart_reset_rx(usart_device);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file HardwareSerial.h
|
||||
* @brief Wirish serial port interface.
|
||||
*/
|
||||
|
||||
#ifndef _HARDWARESERIAL_H_
|
||||
#define _HARDWARESERIAL_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "usart.h"
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
/*
|
||||
* IMPORTANT:
|
||||
*
|
||||
* This class documented "by hand" (i.e., not using Doxygen) in the
|
||||
* leaflabs-docs/ repository.
|
||||
*
|
||||
* If you alter the public HardwareSerial interface, you MUST update
|
||||
* the documentation accordingly.
|
||||
*/
|
||||
|
||||
class HardwareSerial : public Print {
|
||||
public:
|
||||
HardwareSerial(usart_dev *usart_device,
|
||||
uint8 tx_pin,
|
||||
uint8 rx_pin);
|
||||
|
||||
/* Set up/tear down */
|
||||
void begin(uint32 baud);
|
||||
void end(void);
|
||||
|
||||
/* I/O */
|
||||
uint32 available(void);
|
||||
uint32 pending(void);
|
||||
int read(void);
|
||||
void flush(void);
|
||||
virtual void write(unsigned char);
|
||||
using Print::write;
|
||||
|
||||
/* Pin accessors */
|
||||
int txPin(void) { return this->tx_pin; }
|
||||
int rxPin(void) { return this->rx_pin; }
|
||||
private:
|
||||
usart_dev *usart_device;
|
||||
uint8 tx_pin;
|
||||
uint8 rx_pin;
|
||||
};
|
||||
|
||||
extern HardwareSerial Serial1;
|
||||
extern HardwareSerial Serial2;
|
||||
extern HardwareSerial Serial3;
|
||||
#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6)
|
||||
extern HardwareSerial Serial4;
|
||||
extern HardwareSerial Serial5;
|
||||
#endif
|
||||
extern HardwareSerial &SerialDebug;
|
||||
#endif
|
|
@ -0,0 +1,200 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file adc.c
|
||||
*
|
||||
* @brief Analog to digital converter routines
|
||||
*
|
||||
* IMPORTANT: maximum external impedance must be below 0.4kOhms for 1.5
|
||||
* sample conversion time.
|
||||
*
|
||||
* At 55.5 cycles/sample, the external input impedance < 50kOhms.
|
||||
*
|
||||
* See STM32 manual RM0008 for how to calculate this.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "rcc.h"
|
||||
#include "adc.h"
|
||||
|
||||
static adc_dev adc1 = {
|
||||
.regs = ADC1_BASE,
|
||||
.clk_id = RCC_ADC1
|
||||
};
|
||||
/** ADC1 device. */
|
||||
const adc_dev *ADC1 = &adc1;
|
||||
|
||||
static adc_dev adc2 = {
|
||||
.regs = ADC2_BASE,
|
||||
.clk_id = RCC_ADC2
|
||||
};
|
||||
/** ADC2 device. */
|
||||
const adc_dev *ADC2 = &adc2;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
adc_dev adc3 = {
|
||||
.regs = ADC3_BASE,
|
||||
.clk_id = RCC_ADC3
|
||||
};
|
||||
/** ADC3 device. */
|
||||
const adc_dev *ADC3 = &adc3;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize an ADC peripheral.
|
||||
*
|
||||
* Initializes the RCC clock line for the given peripheral. Resets
|
||||
* ADC device registers.
|
||||
*
|
||||
* @param dev ADC peripheral to initialize
|
||||
*/
|
||||
void adc_init(const adc_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
#ifdef STM32F2
|
||||
if(dev->clk_id == RCC_ADC1) {
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
#else
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set external event select for regular group
|
||||
* @param dev ADC device
|
||||
* @param event Event used to trigger the start of conversion.
|
||||
* @see adc_extsel_event
|
||||
*/
|
||||
void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) {
|
||||
uint32 cr2 = dev->regs->CR2;
|
||||
cr2 &= ~ADC_CR2_EXTSEL;
|
||||
cr2 |= event;
|
||||
dev->regs->CR2 = cr2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call a function on all ADC devices.
|
||||
* @param fn Function to call on each ADC device.
|
||||
*/
|
||||
void adc_foreach(void (*fn)(const adc_dev*)) {
|
||||
fn(ADC1);
|
||||
fn(ADC2);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
fn(ADC3);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn the given sample rate into values for ADC_SMPRx. Don't
|
||||
* call this during conversion.
|
||||
* @param dev adc device
|
||||
* @param smp_rate sample rate to set
|
||||
* @see adc_smp_rate
|
||||
*/
|
||||
void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) {
|
||||
uint32 adc_smpr1_val = 0, adc_smpr2_val = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (i < 8) {
|
||||
/* ADC_SMPR1 determines sample time for channels [10,17] */
|
||||
adc_smpr1_val |= smp_rate << (i * 3);
|
||||
}
|
||||
/* ADC_SMPR2 determines sample time for channels [0,9] */
|
||||
adc_smpr2_val |= smp_rate << (i * 3);
|
||||
}
|
||||
|
||||
dev->regs->SMPR1 = adc_smpr1_val;
|
||||
dev->regs->SMPR2 = adc_smpr2_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calibrate an ADC peripheral
|
||||
* @param dev adc device
|
||||
*/
|
||||
void adc_calibrate(const adc_dev *dev) {
|
||||
#ifndef STM32F2
|
||||
__io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3);
|
||||
__io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2);
|
||||
|
||||
*rstcal_bit = 1;
|
||||
while (*rstcal_bit)
|
||||
;
|
||||
|
||||
*cal_bit = 1;
|
||||
while (*cal_bit)
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform a single synchronous software triggered conversion on a
|
||||
* channel.
|
||||
* @param dev ADC device to use for reading.
|
||||
* @param channel channel to convert
|
||||
* @return conversion result
|
||||
*/
|
||||
uint16 adc_read(const adc_dev *dev, uint8 channel) {
|
||||
adc_reg_map *regs = dev->regs;
|
||||
|
||||
adc_set_reg_seqlen(dev, 1);
|
||||
|
||||
regs->SQR3 = channel;
|
||||
regs->CR2 |= ADC_CR2_SWSTART;
|
||||
while(!(regs->SR & ADC_SR_EOC))
|
||||
;
|
||||
|
||||
return (uint16)(regs->DR & ADC_DR_DATA);
|
||||
}
|
||||
|
||||
void setupADC_F2() {
|
||||
#ifdef STM32F2
|
||||
uint32 tmpreg1 = 0;
|
||||
|
||||
tmpreg1 = ADC_COMMON->CCR;
|
||||
|
||||
/* Clear MULTI, DELAY, DMA and ADCPRE bits */
|
||||
#define CR_CLEAR_MASK ((uint32)0xFFFC30E0)
|
||||
tmpreg1 &= CR_CLEAR_MASK;
|
||||
|
||||
/* Configure ADCx: Multi mode, Delay between two sampling time, ADC prescaler,
|
||||
and DMA access mode for multimode */
|
||||
/* Set MULTI bits according to ADC_Mode value */
|
||||
/* Set ADCPRE bits according to ADC_Prescaler value */
|
||||
/* Set DMA bits according to ADC_DMAAccessMode value */
|
||||
/* Set DELAY bits according to ADC_TwoSamplingDelay value */
|
||||
#define ADC_Mode_Independent 0
|
||||
#define ADC_Prescaler_Div2 0
|
||||
#define ADC_DMAAccessMode_Disabled 0 /* DMA mode disabled */
|
||||
#define ADC_TwoSamplingDelay_5Cycles 0
|
||||
|
||||
tmpreg1 |= ADC_Mode_Independent | ADC_Prescaler_Div2 | ADC_DMAAccessMode_Disabled | ADC_TwoSamplingDelay_5Cycles;
|
||||
|
||||
/* Write to ADC CCR */
|
||||
ADC_COMMON->CCR = tmpreg1;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file adc.h
|
||||
*
|
||||
* @brief Analog-to-Digital Conversion (ADC) header.
|
||||
*/
|
||||
|
||||
#ifndef _ADC_H_
|
||||
#define _ADC_H_
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "bitband.h"
|
||||
#include "rcc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef STM32F2
|
||||
typedef struct
|
||||
{
|
||||
__io uint32 CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */
|
||||
__io uint32 CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */
|
||||
__io uint32 CDR; /*!< ADC common regular data register for dual
|
||||
AND triple modes, Address offset: ADC1 base address + 0x308 */
|
||||
} ADC_Common_TypeDef;
|
||||
#define ADC_COMMON ((ADC_Common_TypeDef *) 0x40012300)
|
||||
|
||||
#endif
|
||||
|
||||
/** ADC register map type. */
|
||||
typedef struct adc_reg_map {
|
||||
__io uint32 SR; ///< Status register
|
||||
__io uint32 CR1; ///< Control register 1
|
||||
__io uint32 CR2; ///< Control register 2
|
||||
__io uint32 SMPR1; ///< Sample time register 1
|
||||
__io uint32 SMPR2; ///< Sample time register 2
|
||||
__io uint32 JOFR1; ///< Injected channel data offset register 1
|
||||
__io uint32 JOFR2; ///< Injected channel data offset register 2
|
||||
__io uint32 JOFR3; ///< Injected channel data offset register 3
|
||||
__io uint32 JOFR4; ///< Injected channel data offset register 4
|
||||
__io uint32 HTR; ///< Watchdog high threshold register
|
||||
__io uint32 LTR; ///< Watchdog low threshold register
|
||||
__io uint32 SQR1; ///< Regular sequence register 1
|
||||
__io uint32 SQR2; ///< Regular sequence register 2
|
||||
__io uint32 SQR3; ///< Regular sequence register 3
|
||||
__io uint32 JSQR; ///< Injected sequence register
|
||||
__io uint32 JDR1; ///< Injected data register 1
|
||||
__io uint32 JDR2; ///< Injected data register 2
|
||||
__io uint32 JDR3; ///< Injected data register 3
|
||||
__io uint32 JDR4; ///< Injected data register 4
|
||||
__io uint32 DR; ///< Regular data register
|
||||
} adc_reg_map;
|
||||
|
||||
/** ADC device type. */
|
||||
typedef struct adc_dev {
|
||||
adc_reg_map *regs; /**< Register map */
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
} adc_dev;
|
||||
|
||||
extern const adc_dev *ADC1;
|
||||
extern const adc_dev *ADC2;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
extern const adc_dev *ADC3;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register map base pointers
|
||||
*/
|
||||
|
||||
#ifdef STM32F2
|
||||
/** ADC1 register map base pointer. */
|
||||
#define ADC1_BASE ((struct adc_reg_map*)0x40012000)
|
||||
/** ADC2 register map base pointer. */
|
||||
#define ADC2_BASE ((struct adc_reg_map*)0x40012100)
|
||||
/** ADC3 register map base pointer. */
|
||||
#define ADC3_BASE ((struct adc_reg_map*)0x40012200)
|
||||
#else
|
||||
/** ADC1 register map base pointer. */
|
||||
#define ADC1_BASE ((struct adc_reg_map*)0x40012400)
|
||||
/** ADC2 register map base pointer. */
|
||||
#define ADC2_BASE ((struct adc_reg_map*)0x40012800)
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
/** ADC3 register map base pointer. */
|
||||
#define ADC3_BASE ((struct adc_reg_map*)0x40013C00)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define ADC_SR_AWD_BIT 0
|
||||
#define ADC_SR_EOC_BIT 1
|
||||
#define ADC_SR_JEOC_BIT 2
|
||||
#define ADC_SR_JSTRT_BIT 3
|
||||
#define ADC_SR_STRT_BIT 4
|
||||
|
||||
#define ADC_SR_AWD BIT(ADC_SR_AWD_BIT)
|
||||
#define ADC_SR_EOC BIT(ADC_SR_EOC_BIT)
|
||||
#define ADC_SR_JEOC BIT(ADC_SR_JEOC_BIT)
|
||||
#define ADC_SR_JSTRT BIT(ADC_SR_JSTRT_BIT)
|
||||
#define ADC_SR_STRT BIT(ADC_SR_STRT_BIT)
|
||||
|
||||
/* Control register 1 */
|
||||
|
||||
#define ADC_CR1_EOCIE_BIT 5
|
||||
#define ADC_CR1_AWDIE_BIT 6
|
||||
#define ADC_CR1_JEOCIE_BIT 7
|
||||
#define ADC_CR1_SCAN_BIT 8
|
||||
#define ADC_CR1_AWDSGL_BIT 9
|
||||
#define ADC_CR1_JAUTO_BIT 10
|
||||
#define ADC_CR1_DISCEN_BIT 11
|
||||
#define ADC_CR1_JDISCEN_BIT 12
|
||||
#define ADC_CR1_JAWDEN_BIT 22
|
||||
#define ADC_CR1_AWDEN_BIT 23
|
||||
|
||||
#define ADC_CR1_AWDCH (0x1F)
|
||||
#define ADC_CR1_EOCIE BIT(ADC_CR1_EOCIE_BIT)
|
||||
#define ADC_CR1_AWDIE BIT(ADC_CR1_AWDIE_BIT)
|
||||
#define ADC_CR1_JEOCIE BIT(ADC_CR1_JEOCIE_BIT)
|
||||
#define ADC_CR1_SCAN BIT(ADC_CR1_SCAN_BIT)
|
||||
#define ADC_CR1_AWDSGL BIT(ADC_CR1_AWDSGL_BIT)
|
||||
#define ADC_CR1_JAUTO BIT(ADC_CR1_JAUTO_BIT)
|
||||
#define ADC_CR1_DISCEN BIT(ADC_CR1_DISCEN_BIT)
|
||||
#define ADC_CR1_JDISCEN BIT(ADC_CR1_JDISCEN_BIT)
|
||||
#define ADC_CR1_DISCNUM (0xE000)
|
||||
#define ADC_CR1_JAWDEN BIT(ADC_CR1_JAWDEN_BIT)
|
||||
#define ADC_CR1_AWDEN BIT(ADC_CR1_AWDEN_BIT)
|
||||
|
||||
/* Control register 2 */
|
||||
|
||||
#define ADC_CR2_ADON_BIT 0
|
||||
#define ADC_CR2_CONT_BIT 1
|
||||
#define ADC_CR2_CAL_BIT 2
|
||||
#define ADC_CR2_RSTCAL_BIT 3
|
||||
#define ADC_CR2_DMA_BIT 8
|
||||
#define ADC_CR2_ALIGN_BIT 11
|
||||
#define ADC_CR2_JEXTTRIG_BIT 15
|
||||
#define ADC_CR2_EXTTRIG_BIT 20
|
||||
#define ADC_CR2_TSEREFE_BIT 23
|
||||
#ifdef STM32F2
|
||||
#define ADC_CR2_JSWSTART_BIT 22
|
||||
#define ADC_CR2_SWSTART_BIT 30
|
||||
#define ADC_CR2_EXTSEL (0x0F000000)
|
||||
#define ADC_CR2_JEXTSEL (0x000F0000)
|
||||
#else
|
||||
#define ADC_CR2_JSWSTART_BIT 21
|
||||
#define ADC_CR2_SWSTART_BIT 22
|
||||
#define ADC_CR2_EXTSEL (0x000E0000)
|
||||
#define ADC_CR2_JEXTSEL (0x00007000)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define ADC_CR2_ADON BIT(ADC_CR2_ADON_BIT)
|
||||
#define ADC_CR2_CONT BIT(ADC_CR2_CONT_BIT)
|
||||
#define ADC_CR2_CAL BIT(ADC_CR2_CAL_BIT)
|
||||
#define ADC_CR2_RSTCAL BIT(ADC_CR2_RSTCAL_BIT)
|
||||
#define ADC_CR2_DMA BIT(ADC_CR2_DMA_BIT)
|
||||
#define ADC_CR2_ALIGN BIT(ADC_CR2_ALIGN_BIT)
|
||||
#define ADC_CR2_JEXTTRIG BIT(ADC_CR2_JEXTTRIG_BIT)
|
||||
#define ADC_CR2_EXTTRIG BIT(ADC_CR2_EXTTRIG_BIT)
|
||||
#define ADC_CR2_JSWSTART BIT(ADC_CR2_JSWSTART_BIT)
|
||||
#define ADC_CR2_SWSTART BIT(ADC_CR2_SWSTART_BIT)
|
||||
#define ADC_CR2_TSEREFE BIT(ADC_CR2_TSEREFE_BIT)
|
||||
|
||||
/* Sample time register 1 */
|
||||
|
||||
#define ADC_SMPR1_SMP17 (0x7 << 21)
|
||||
#define ADC_SMPR1_SMP16 (0x7 << 18)
|
||||
#define ADC_SMPR1_SMP15 (0x7 << 15)
|
||||
#define ADC_SMPR1_SMP14 (0x7 << 12)
|
||||
#define ADC_SMPR1_SMP13 (0x7 << 9)
|
||||
#define ADC_SMPR1_SMP12 (0x7 << 6)
|
||||
#define ADC_SMPR1_SMP11 (0x7 << 3)
|
||||
#define ADC_SMPR1_SMP10 0x7
|
||||
|
||||
/* Sample time register 2 */
|
||||
|
||||
#define ADC_SMPR2_SMP9 (0x7 << 27)
|
||||
#define ADC_SMPR2_SMP8 (0x7 << 24)
|
||||
#define ADC_SMPR2_SMP7 (0x7 << 21)
|
||||
#define ADC_SMPR2_SMP6 (0x7 << 18)
|
||||
#define ADC_SMPR2_SMP5 (0x7 << 15)
|
||||
#define ADC_SMPR2_SMP4 (0x7 << 12)
|
||||
#define ADC_SMPR2_SMP3 (0x7 << 9)
|
||||
#define ADC_SMPR2_SMP2 (0x7 << 6)
|
||||
#define ADC_SMPR2_SMP1 (0x7 << 3)
|
||||
#define ADC_SMPR2_SMP0 0x7
|
||||
|
||||
/* Injected channel data offset register */
|
||||
|
||||
#define ADC_JOFR_JOFFSET 0x3FF
|
||||
|
||||
/* Watchdog high threshold register */
|
||||
|
||||
#define ADC_HTR_HT 0x3FF
|
||||
|
||||
/* Watchdog low threshold register */
|
||||
|
||||
#define ADC_LTR_LT 0x3FF
|
||||
|
||||
/* Regular sequence register 1 */
|
||||
|
||||
#define ADC_SQR1_L (0x1F << 20)
|
||||
#define ADC_SQR1_SQ16 (0x1F << 15)
|
||||
#define ADC_SQR1_SQ15 (0x1F << 10)
|
||||
#define ADC_SQR1_SQ14 (0x1F << 5)
|
||||
#define ADC_SQR1_SQ13 0x1F
|
||||
|
||||
/* Regular sequence register 2 */
|
||||
|
||||
#define ADC_SQR2_SQ12 (0x1F << 25)
|
||||
#define ADC_SQR2_SQ11 (0x1F << 20)
|
||||
#define ADC_SQR2_SQ10 (0x1F << 16)
|
||||
#define ADC_SQR2_SQ9 (0x1F << 10)
|
||||
#define ADC_SQR2_SQ8 (0x1F << 5)
|
||||
#define ADC_SQR2_SQ7 0x1F
|
||||
|
||||
/* Regular sequence register 3 */
|
||||
|
||||
#define ADC_SQR3_SQ6 (0x1F << 25)
|
||||
#define ADC_SQR3_SQ5 (0x1F << 20)
|
||||
#define ADC_SQR3_SQ4 (0x1F << 16)
|
||||
#define ADC_SQR3_SQ3 (0x1F << 10)
|
||||
#define ADC_SQR3_SQ2 (0x1F << 5)
|
||||
#define ADC_SQR3_SQ1 0x1F
|
||||
|
||||
/* Injected sequence register */
|
||||
|
||||
#define ADC_JSQR_JL (0x3 << 20)
|
||||
#define ADC_JSQR_JL_1CONV (0x0 << 20)
|
||||
#define ADC_JSQR_JL_2CONV (0x1 << 20)
|
||||
#define ADC_JSQR_JL_3CONV (0x2 << 20)
|
||||
#define ADC_JSQR_JL_4CONV (0x3 << 20)
|
||||
#define ADC_JSQR_JSQ4 (0x1F << 15)
|
||||
#define ADC_JSQR_JSQ3 (0x1F << 10)
|
||||
#define ADC_JSQR_JSQ2 (0x1F << 5)
|
||||
#define ADC_JSQR_JSQ1 0x1F
|
||||
|
||||
/* Injected data registers */
|
||||
|
||||
#define ADC_JDR_JDATA 0xFFFF
|
||||
|
||||
/* Regular data register */
|
||||
|
||||
#define ADC_DR_ADC2DATA (0xFFFF << 16)
|
||||
#define ADC_DR_DATA 0xFFFF
|
||||
|
||||
void adc_init(const adc_dev *dev);
|
||||
|
||||
/**
|
||||
* @brief External event selector for regular group conversion.
|
||||
* @see adc_set_extsel
|
||||
*/
|
||||
typedef enum adc_extsel_event {
|
||||
ADC_ADC12_TIM1_CC1 = (0 << 17), /**< ADC1 and ADC2: Timer 1 CC1 event */
|
||||
ADC_ADC12_TIM1_CC2 = (1 << 17), /**< ADC1 and ADC2: Timer 1 CC2 event */
|
||||
ADC_ADC12_TIM1_CC3 = (2 << 17), /**< ADC1 and ADC2: Timer 1 CC3 event */
|
||||
ADC_ADC12_TIM2_CC2 = (3 << 17), /**< ADC1 and ADC2: Timer 2 CC2 event */
|
||||
ADC_ADC12_TIM3_TRGO = (4 << 17), /**< ADC1 and ADC2: Timer 3 TRGO event */
|
||||
ADC_ADC12_TIM4_CC4 = (5 << 17), /**< ADC1 and ADC2: Timer 4 CC4 event */
|
||||
ADC_ADC12_EXTI11 = (6 << 17), /**< ADC1 and ADC2: EXTI11 event */
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
ADC_ADC12_TIM8_TRGO = (6 << 17), /**< ADC1 and ADC2: Timer 8 TRGO
|
||||
event (high density only) */
|
||||
#endif
|
||||
ADC_ADC12_SWSTART = (7 << 17), /**< ADC1 and ADC2: Software start */
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
ADC_ADC3_TIM3_CC1 = (0 << 17), /**< ADC3: Timer 3 CC1 event
|
||||
(high density only) */
|
||||
ADC_ADC3_TIM2_CC3 = (1 << 17), /**< ADC3: Timer 2 CC3 event
|
||||
(high density only) */
|
||||
ADC_ADC3_TIM1_CC3 = (2 << 17), /**< ADC3: Timer 1 CC3 event
|
||||
(high density only) */
|
||||
ADC_ADC3_TIM8_CC1 = (3 << 17), /**< ADC3: Timer 8 CC1 event
|
||||
(high density only) */
|
||||
ADC_ADC3_TIM8_TRGO = (4 << 17), /**< ADC3: Timer 8 TRGO event
|
||||
(high density only) */
|
||||
ADC_ADC3_TIM5_CC1 = (5 << 17), /**< ADC3: Timer 5 CC1 event
|
||||
(high density only) */
|
||||
ADC_ADC3_TIM5_CC3 = (6 << 17), /**< ADC3: Timer 5 CC3 event
|
||||
(high density only) */
|
||||
ADC_ADC3_SWSTART = (7 << 17), /**< ADC3: Software start (high
|
||||
density only) */
|
||||
#endif
|
||||
ADC_SWSTART = (7 << 17) /**< ADC1, ADC2, ADC3: Software start */
|
||||
} adc_extsel_event;
|
||||
|
||||
void adc_set_extsel(const adc_dev *dev, adc_extsel_event event);
|
||||
void adc_foreach(void (*fn)(const adc_dev*));
|
||||
|
||||
/**
|
||||
* @brief ADC sample times, in ADC clock cycles
|
||||
*
|
||||
* These control the amount of time spent sampling the input voltage.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_SMPR_1_5, /**< 1.5 ADC cycles */
|
||||
ADC_SMPR_7_5, /**< 7.5 ADC cycles */
|
||||
ADC_SMPR_13_5, /**< 13.5 ADC cycles */
|
||||
ADC_SMPR_28_5, /**< 28.5 ADC cycles */
|
||||
ADC_SMPR_41_5, /**< 41.5 ADC cycles */
|
||||
ADC_SMPR_55_5, /**< 55.5 ADC cycles */
|
||||
ADC_SMPR_71_5, /**< 71.5 ADC cycles */
|
||||
ADC_SMPR_239_5 /**< 239.5 ADC cycles */
|
||||
} adc_smp_rate;
|
||||
|
||||
void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate);
|
||||
void adc_calibrate(const adc_dev *dev);
|
||||
uint16 adc_read(const adc_dev *dev, uint8 channel);
|
||||
|
||||
/**
|
||||
* @brief Set the regular channel sequence length.
|
||||
*
|
||||
* Defines the total number of conversions in the regular channel
|
||||
* conversion sequence.
|
||||
*
|
||||
* @param dev ADC device.
|
||||
* @param length Regular channel sequence length, from 1 to 16.
|
||||
*/
|
||||
static inline void adc_set_reg_seqlen(const adc_dev *dev, uint8 length) {
|
||||
uint32 tmp = dev->regs->SQR1;
|
||||
tmp &= ~ADC_SQR1_L;
|
||||
tmp |= (length - 1) << 20;
|
||||
dev->regs->SQR1 = tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set external trigger conversion mode event for regular channels
|
||||
* @param dev ADC device
|
||||
* @param enable If 1, conversion on external events is enabled; if 0,
|
||||
* disabled.
|
||||
*/
|
||||
static inline void adc_set_exttrig(const adc_dev *dev, uint8 enable) {
|
||||
*bb_perip(&dev->regs->CR2, ADC_CR2_EXTTRIG_BIT) = !!enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable an adc peripheral
|
||||
* @param dev ADC device to enable
|
||||
*/
|
||||
static inline void adc_enable(const adc_dev *dev) {
|
||||
*bb_perip(&dev->regs->CR2, ADC_CR2_ADON_BIT) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable an ADC peripheral
|
||||
* @param dev ADC device to disable
|
||||
*/
|
||||
static inline void adc_disable(const adc_dev *dev) {
|
||||
*bb_perip(&dev->regs->CR2, ADC_CR2_ADON_BIT) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable all ADC peripherals.
|
||||
*/
|
||||
static inline void adc_disable_all(void) {
|
||||
adc_foreach(adc_disable);
|
||||
}
|
||||
|
||||
void setupADC_F2();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,120 @@
|
|||
/******************************************************************************
|
||||
* 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 bitband.h
|
||||
*
|
||||
* @brief Bit-banding utility functions
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
#ifndef _BITBAND_H_
|
||||
#define _BITBAND_H_
|
||||
|
||||
#define BB_SRAM_REF 0x20000000
|
||||
#define BB_SRAM_BASE 0x22000000
|
||||
#define BB_PERI_REF 0x40000000
|
||||
#define BB_PERI_BASE 0x42000000
|
||||
|
||||
static inline volatile uint32* __bb_addr(volatile void*,
|
||||
uint32,
|
||||
uint32,
|
||||
uint32);
|
||||
|
||||
/**
|
||||
* @brief Obtain a pointer to the bit-band address corresponding to a
|
||||
* bit in a volatile SRAM address.
|
||||
* @param address Address in the bit-banded SRAM region
|
||||
* @param bit Bit in address to bit-band
|
||||
*/
|
||||
static inline volatile uint32* bb_sramp(volatile void *address, uint32 bit) {
|
||||
return __bb_addr(address, bit, BB_SRAM_BASE, BB_SRAM_REF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a bit from an address in the SRAM bit-band region.
|
||||
* @param address Address in the SRAM bit-band region to read from
|
||||
* @param bit Bit in address to read
|
||||
* @return bit's value in address.
|
||||
*/
|
||||
static inline uint8 bb_sram_get_bit(volatile void *address, uint32 bit) {
|
||||
return *bb_sramp(address, bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a bit in an address in the SRAM bit-band region.
|
||||
* @param address Address in the SRAM bit-band region to write to
|
||||
* @param bit Bit in address to write to
|
||||
* @param val Value to write for bit, either 0 or 1.
|
||||
*/
|
||||
static inline void bb_sram_set_bit(volatile void *address,
|
||||
uint32 bit,
|
||||
uint8 val) {
|
||||
*bb_sramp(address, bit) = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Obtain a pointer to the bit-band address corresponding to a
|
||||
* bit in a peripheral address.
|
||||
* @param address Address in the bit-banded peripheral region
|
||||
* @param bit Bit in address to bit-band
|
||||
*/
|
||||
static inline volatile uint32* bb_perip(volatile void *address, uint32 bit) {
|
||||
return __bb_addr(address, bit, BB_PERI_BASE, BB_PERI_REF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a bit from an address in the peripheral bit-band region.
|
||||
* @param address Address in the peripheral bit-band region to read from
|
||||
* @param bit Bit in address to read
|
||||
* @return bit's value in address.
|
||||
*/
|
||||
static inline uint8 bb_peri_get_bit(volatile void *address, uint32 bit) {
|
||||
return *bb_perip(address, bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a bit in an address in the peripheral bit-band region.
|
||||
* @param address Address in the peripheral bit-band region to write to
|
||||
* @param bit Bit in address to write to
|
||||
* @param val Value to write for bit, either 0 or 1.
|
||||
*/
|
||||
static inline void bb_peri_set_bit(volatile void *address,
|
||||
uint32 bit,
|
||||
uint8 val) {
|
||||
*bb_perip(address, bit) = val;
|
||||
}
|
||||
|
||||
static inline volatile uint32* __bb_addr(volatile void *address,
|
||||
uint32 bit,
|
||||
uint32 bb_base,
|
||||
uint32 bb_ref) {
|
||||
return (volatile uint32*)(bb_base + ((uint32)address - bb_ref) * 32 +
|
||||
bit * 4);
|
||||
}
|
||||
|
||||
#endif /* _BITBAND_H_ */
|
|
@ -0,0 +1,129 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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 bkp.c
|
||||
* @brief Backup register support.
|
||||
*/
|
||||
|
||||
#include "bkp.h"
|
||||
#include "pwr.h"
|
||||
#include "rcc.h"
|
||||
#include "bitband.h"
|
||||
|
||||
static inline __io uint32* data_register(uint8 reg);
|
||||
|
||||
bkp_dev bkp = {
|
||||
.regs = BKP_BASE,
|
||||
};
|
||||
/** Backup device. */
|
||||
const bkp_dev *BKP = &bkp;
|
||||
|
||||
/**
|
||||
* @brief Initialize backup interface.
|
||||
*
|
||||
* Enables the power and backup interface clocks, and resets the
|
||||
* backup device.
|
||||
*/
|
||||
void bkp_init(void) {
|
||||
/* Don't call pwr_init(), or you'll reset the device. We just
|
||||
* need the clock. */
|
||||
rcc_clk_enable(RCC_PWR);
|
||||
rcc_clk_enable(RCC_BKP);
|
||||
rcc_reset_dev(RCC_BKP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable write access to the backup registers. Backup interface must
|
||||
* be initialized for subsequent register writes to work.
|
||||
* @see bkp_init()
|
||||
*/
|
||||
void bkp_enable_writes(void) {
|
||||
*bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable write access to the backup registers.
|
||||
*/
|
||||
void bkp_disable_writes(void) {
|
||||
*bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a value from given backup data register.
|
||||
* @param reg Data register to read, from 1 to BKP_NR_DATA_REGS (10 on
|
||||
* medium-density devices, 42 on high-density devices).
|
||||
*/
|
||||
uint16 bkp_read(uint8 reg) {
|
||||
__io uint32* dr = data_register(reg);
|
||||
if (!dr) {
|
||||
ASSERT(0); /* nonexistent register */
|
||||
return 0;
|
||||
}
|
||||
return (uint16)*dr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value to given data register.
|
||||
*
|
||||
* Write access to backup registers must be enabled.
|
||||
*
|
||||
* @param reg Data register to write, from 1 to BKP_NR_DATA_REGS (10
|
||||
* on medium-density devices, 42 on high-density devices).
|
||||
* @param val Value to write into the register.
|
||||
* @see bkp_enable_writes()
|
||||
*/
|
||||
void bkp_write(uint8 reg, uint16 val) {
|
||||
__io uint32* dr = data_register(reg);
|
||||
if (!dr) {
|
||||
ASSERT(0); /* nonexistent register */
|
||||
return;
|
||||
}
|
||||
*dr = (uint32)val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Data register memory layout is not contiguous. It's split up from
|
||||
* 1--NR_LOW_DRS, beginning at BKP_BASE->DR1, through to
|
||||
* (NR_LOW_DRS+1)--BKP_NR_DATA_REGS, beginning at BKP_BASE->DR11.
|
||||
*/
|
||||
#define NR_LOW_DRS 10
|
||||
|
||||
static inline __io uint32* data_register(uint8 reg) {
|
||||
if (reg < 1 || reg > BKP_NR_DATA_REGS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if BKP_NR_DATA_REGS == NR_LOW_DRS
|
||||
return (uint32*)BKP_BASE + reg;
|
||||
#else
|
||||
if (reg <= NR_LOW_DRS) {
|
||||
return (uint32*)BKP_BASE + reg;
|
||||
} else {
|
||||
return (uint32*)&(BKP_BASE->DR11) + (reg - NR_LOW_DRS - 1);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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 bkp.h
|
||||
* @brief Backup register support.
|
||||
*/
|
||||
|
||||
#ifndef _BKP_H_
|
||||
#define _BKP_H_
|
||||
|
||||
#include "libmaple.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(STM32_MEDIUM_DENSITY)
|
||||
#define BKP_NR_DATA_REGS 10
|
||||
#elif defined(STM32_HIGH_DENSITY)
|
||||
#define BKP_NR_DATA_REGS 42
|
||||
#endif
|
||||
|
||||
/** Backup peripheral register map type. */
|
||||
typedef struct bkp_reg_map {
|
||||
const uint32 RESERVED1; ///< Reserved
|
||||
__io uint32 DR1; ///< Data register 1
|
||||
__io uint32 DR2; ///< Data register 2
|
||||
__io uint32 DR3; ///< Data register 3
|
||||
__io uint32 DR4; ///< Data register 4
|
||||
__io uint32 DR5; ///< Data register 5
|
||||
__io uint32 DR6; ///< Data register 6
|
||||
__io uint32 DR7; ///< Data register 7
|
||||
__io uint32 DR8; ///< Data register 8
|
||||
__io uint32 DR9; ///< Data register 9
|
||||
__io uint32 DR10; ///< Data register 10
|
||||
__io uint32 RTCCR; ///< RTC control register
|
||||
__io uint32 CR; ///< Control register
|
||||
__io uint32 CSR; ///< Control and status register
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
const uint32 RESERVED2; ///< Reserved
|
||||
const uint32 RESERVED3; ///< Reserved
|
||||
__io uint32 DR11; ///< Data register 11
|
||||
__io uint32 DR12; ///< Data register 12
|
||||
__io uint32 DR13; ///< Data register 13
|
||||
__io uint32 DR14; ///< Data register 14
|
||||
__io uint32 DR15; ///< Data register 15
|
||||
__io uint32 DR16; ///< Data register 16
|
||||
__io uint32 DR17; ///< Data register 17
|
||||
__io uint32 DR18; ///< Data register 18
|
||||
__io uint32 DR19; ///< Data register 19
|
||||
__io uint32 DR20; ///< Data register 20
|
||||
__io uint32 DR21; ///< Data register 21
|
||||
__io uint32 DR22; ///< Data register 22
|
||||
__io uint32 DR23; ///< Data register 23
|
||||
__io uint32 DR24; ///< Data register 24
|
||||
__io uint32 DR25; ///< Data register 25
|
||||
__io uint32 DR26; ///< Data register 26
|
||||
__io uint32 DR27; ///< Data register 27
|
||||
__io uint32 DR28; ///< Data register 28
|
||||
__io uint32 DR29; ///< Data register 29
|
||||
__io uint32 DR30; ///< Data register 30
|
||||
__io uint32 DR31; ///< Data register 31
|
||||
__io uint32 DR32; ///< Data register 32
|
||||
__io uint32 DR33; ///< Data register 33
|
||||
__io uint32 DR34; ///< Data register 34
|
||||
__io uint32 DR35; ///< Data register 35
|
||||
__io uint32 DR36; ///< Data register 36
|
||||
__io uint32 DR37; ///< Data register 37
|
||||
__io uint32 DR38; ///< Data register 38
|
||||
__io uint32 DR39; ///< Data register 39
|
||||
__io uint32 DR40; ///< Data register 40
|
||||
__io uint32 DR41; ///< Data register 41
|
||||
__io uint32 DR42; ///< Data register 42
|
||||
#endif
|
||||
} bkp_reg_map;
|
||||
|
||||
/** Backup peripheral register map base pointer. */
|
||||
#define BKP_BASE ((struct bkp_reg_map*)0x40006C00)
|
||||
|
||||
/** Backup peripheral device type. */
|
||||
typedef struct bkp_dev {
|
||||
bkp_reg_map *regs; /**< Register map */
|
||||
} bkp_dev;
|
||||
|
||||
extern const bkp_dev *BKP;
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Data Registers */
|
||||
|
||||
#define BKP_DR_D 0xFFFF
|
||||
|
||||
/* RTC Clock Calibration Register */
|
||||
|
||||
#define BKP_RTCCR_ASOS_BIT 9
|
||||
#define BKP_RTCCR_ASOE_BIT 8
|
||||
#define BKP_RTCCR_CCO_BIT 7
|
||||
|
||||
#define BKP_RTCCR_ASOS BIT(BKP_RTCCR_ASOS_BIT)
|
||||
#define BKP_RTCCR_ASOE BIT(BKP_RTCCR_ASOE_BIT)
|
||||
#define BKP_RTCCR_CCO BIT(BKP_RTCCR_CCO_BIT)
|
||||
#define BKP_RTCCR_CAL 0x7F
|
||||
|
||||
/* Backup control register */
|
||||
|
||||
#define BKP_CR_TPAL_BIT 1
|
||||
#define BKP_CR_TPE_BIT 0
|
||||
|
||||
#define BKP_CR_TPAL BIT(BKP_CR_TPAL_BIT)
|
||||
#define BKP_CR_TPE BIT(BKP_CR_TPE_BIT)
|
||||
|
||||
/* Backup control/status register */
|
||||
|
||||
#define BKP_CSR_TIF_BIT 9
|
||||
#define BKP_CSR_TEF_BIT 8
|
||||
#define BKP_CSR_TPIE_BIT 2
|
||||
#define BKP_CSR_CTI_BIT 1
|
||||
#define BKP_CSR_CTE_BIT 0
|
||||
|
||||
#define BKP_CSR_TIF BIT(BKP_CSR_TIF_BIT)
|
||||
#define BKP_CSR_TEF BIT(BKP_CSR_TEF_BIT)
|
||||
#define BKP_CSR_TPIE BIT(BKP_CSR_TPIE_BIT)
|
||||
#define BKP_CSR_CTI BIT(BKP_CSR_CTI_BIT)
|
||||
#define BKP_CSR_CTE BIT(BKP_CSR_CTE_BIT)
|
||||
|
||||
/*
|
||||
* Convenience functions
|
||||
*/
|
||||
|
||||
void bkp_init(void);
|
||||
void bkp_enable_writes(void);
|
||||
void bkp_disable_writes(void);
|
||||
uint16 bkp_read(uint8 reg);
|
||||
void bkp_write(uint8 reg, uint16 val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,155 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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 dac.c
|
||||
* @brief Digital to analog converter support.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "gpio.h"
|
||||
#include "dac.h"
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
|
||||
/**
|
||||
* @brief DAC peripheral routines.
|
||||
*/
|
||||
|
||||
dac_dev dac = {
|
||||
.regs = DAC_BASE,
|
||||
};
|
||||
/** DAC device. */
|
||||
const dac_dev *DAC = &dac;
|
||||
|
||||
/**
|
||||
* @brief Initialize the digital to analog converter
|
||||
* @param dev DAC device
|
||||
* @param flags Flags:
|
||||
* DAC_CH1: Enable channel 1
|
||||
* DAC_CH2: Enable channel 2
|
||||
* @sideeffect May set PA4 or PA5 to INPUT_ANALOG
|
||||
*/
|
||||
void dac_init(const dac_dev *dev, uint32 flags) {
|
||||
/* First turn on the clock */
|
||||
rcc_clk_enable(RCC_DAC);
|
||||
rcc_reset_dev(RCC_DAC);
|
||||
|
||||
if (flags & DAC_CH1) {
|
||||
dac_enable_channel(dev, 1);
|
||||
}
|
||||
|
||||
if (flags & DAC_CH2) {
|
||||
dac_enable_channel(dev, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the output buffer of the digital to analog converter
|
||||
* @param dev DAC device
|
||||
* @param flags Flags:
|
||||
* DAC_CH1: Select channel 1
|
||||
* DAC_CH2: Select channel 2
|
||||
* @param status Status:
|
||||
* 1: enable buffer
|
||||
* 0: disable buffer
|
||||
*/
|
||||
void dac_enable_buffer(const dac_dev *dev, uint32 flags, int status) {
|
||||
if (flags & DAC_CH1) {
|
||||
if(status) {
|
||||
dev->regs->CR &= ~DAC_CR_BOFF1;
|
||||
} else {
|
||||
dev->regs->CR |= DAC_CR_BOFF1;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DAC_CH2) {
|
||||
if(status) {
|
||||
dev->regs->CR &= ~DAC_CR_BOFF2;
|
||||
} else {
|
||||
dev->regs->CR |= DAC_CR_BOFF2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a 12-bit value to the DAC to output
|
||||
* @param dev DAC device
|
||||
* @param channel channel to select (1 or 2)
|
||||
* @param val value to write
|
||||
*/
|
||||
void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val) {
|
||||
switch(channel) {
|
||||
case 1:
|
||||
dev->regs->DHR12R1 = DAC_DHR12R1_DACC1DHR & val;
|
||||
break;
|
||||
case 2:
|
||||
dev->regs->DHR12R2 = DAC_DHR12R2_DACC2DHR & val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a DAC channel
|
||||
* @param dev DAC device
|
||||
* @param channel channel to enable, either 1 or 2
|
||||
* @sideeffect May change pin mode of PA4 or PA5
|
||||
*/
|
||||
void dac_enable_channel(const dac_dev *dev, uint8 channel) {
|
||||
/*
|
||||
* Setup ANALOG mode on PA4 and PA5. This mapping is consistent across
|
||||
* all STM32 chips with a DAC. See RM0008 12.2.
|
||||
*/
|
||||
switch (channel) {
|
||||
case 1:
|
||||
gpio_set_mode(GPIOA, 4, GPIO_INPUT_ANALOG);
|
||||
dev->regs->CR |= DAC_CR_EN1;
|
||||
break;
|
||||
case 2:
|
||||
gpio_set_mode(GPIOA, 5, GPIO_INPUT_ANALOG);
|
||||
dev->regs->CR |= DAC_CR_EN2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a DAC channel
|
||||
* @param dev DAC device
|
||||
* @param channel channel to disable, either 1 or 2
|
||||
*/
|
||||
void dac_disable_channel(const dac_dev *dev, uint8 channel) {
|
||||
switch (channel) {
|
||||
case 1:
|
||||
dev->regs->CR &= ~DAC_CR_EN1;
|
||||
break;
|
||||
case 2:
|
||||
dev->regs->CR &= ~DAC_CR_EN2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STM32_HIGH_DENSITY */
|
|
@ -0,0 +1,169 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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 dac.h
|
||||
* @brief Digital to analog converter support.
|
||||
*/
|
||||
|
||||
/* See notes/dac.txt for more info */
|
||||
|
||||
#ifndef _DAC_H_
|
||||
#define _DAC_H_
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register maps
|
||||
*/
|
||||
|
||||
/** DAC register map. */
|
||||
typedef struct dac_reg_map {
|
||||
__io uint32 CR; /**< Control register */
|
||||
__io uint32 SWTRIGR; /**< Software trigger register */
|
||||
__io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data
|
||||
holding register */
|
||||
__io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding
|
||||
register */
|
||||
__io uint32 DOR1; /**< Channel 1 data output register */
|
||||
__io uint32 DOR2; /**< Channel 2 data output register */
|
||||
} dac_reg_map;
|
||||
|
||||
/** DAC register map base address */
|
||||
#define DAC_BASE ((struct dac_reg_map*)0x40007400)
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
/** DAC device type. */
|
||||
typedef struct dac_dev {
|
||||
dac_reg_map *regs; /**< Register map */
|
||||
} dac_dev;
|
||||
|
||||
extern const dac_dev *DAC;
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Control register */
|
||||
/* Channel 1 control */
|
||||
#define DAC_CR_EN1 BIT(0) /* Enable */
|
||||
#define DAC_CR_BOFF1 BIT(1) /* Output buffer disable */
|
||||
#define DAC_CR_TEN1 BIT(2) /* Trigger enable */
|
||||
#define DAC_CR_TSEL1 (0x7 << 3) /* Trigger selection */
|
||||
#define DAC_CR_WAVE1 (0x3 << 6) /* Noise/triangle wave enable */
|
||||
#define DAC_CR_MAMP1 (0xF << 8) /* Mask/amplitude selector */
|
||||
#define DAC_CR_DMAEN1 BIT(12) /* DMA enable */
|
||||
/* Channel 2 control */
|
||||
#define DAC_CR_EN2 BIT(16) /* Enable */
|
||||
#define DAC_CR_BOFF2 BIT(17) /* Output buffer disable */
|
||||
#define DAC_CR_TEN2 BIT(18) /* Trigger enable */
|
||||
#define DAC_CR_TSEL2 (0x7 << 19) /* Trigger selection */
|
||||
#define DAC_CR_WAVE2 (0x3 << 22) /* Noise/triangle wave generation*/
|
||||
#define DAC_CR_MAMP2 (0xF << 24) /* Mask/amplitude selector */
|
||||
#define DAC_CR_DMAEN2 BIT(28) /* DMA enable */
|
||||
|
||||
/* Software trigger register */
|
||||
#define DAC_SWTRIGR_SWTRIG1 BIT(0) /* Channel 1 software trigger */
|
||||
#define DAC_SWTRIGR_SWTRIG2 BIT(1) /* Channel 2 software trigger */
|
||||
|
||||
/* Channel 1 12-bit right-aligned data holding register */
|
||||
#define DAC_DHR12R1_DACC1DHR 0x00000FFF
|
||||
|
||||
/* Channel 1 12-bit left-aligned data holding register */
|
||||
#define DAC_DHR12L1_DACC1DHR 0x0000FFF0
|
||||
|
||||
/* Channel 1 8-bit left-aligned data holding register */
|
||||
#define DAC_DHR8R1_DACC1DHR 0x000000FF
|
||||
|
||||
/* Channel 2 12-bit right-aligned data holding register */
|
||||
#define DAC_DHR12R2_DACC2DHR 0x00000FFF
|
||||
|
||||
/* Channel 2 12-bit left-aligned data holding register */
|
||||
#define DAC_DHR12L2_DACC2DHR 0x0000FFF0
|
||||
|
||||
/* Channel 2 8-bit left-aligned data holding register */
|
||||
#define DAC_DHR8R2_DACC2DHR 0x000000FF
|
||||
|
||||
/* Dual DAC 12-bit right-aligned data holding register */
|
||||
#define DAC_DHR12RD_DACC1DHR 0x00000FFF
|
||||
#define DAC_DHR12RD_DACC2DHR 0x0FFF0000
|
||||
|
||||
/* Dual DAC 12-bit left-aligned data holding register */
|
||||
#define DAC_DHR12LD_DACC1DHR 0x0000FFF0
|
||||
#define DAC_DHR12LD_DACC2DHR 0xFFF00000
|
||||
|
||||
/* Dual DAC 8-bit left-aligned data holding register */
|
||||
#define DAC_DHR8RD_DACC1DHR 0x000000FF
|
||||
#define DAC_DHR8RD_DACC2DHR 0x0000FF00
|
||||
|
||||
/* Channel 1 data output register */
|
||||
#define DAC_DOR1_DACC1DOR 0x00000FFF
|
||||
|
||||
/* Channel 1 data output register */
|
||||
#define DAC_DOR2_DACC2DOR 0x00000FFF
|
||||
|
||||
/*
|
||||
* Convenience functions
|
||||
*/
|
||||
|
||||
/* We take the dev argument in these convenience functions for
|
||||
* future-proofing */
|
||||
|
||||
#define DAC_CH1 0x1
|
||||
#define DAC_CH2 0x2
|
||||
void dac_init(const dac_dev *dev, uint32 flags);
|
||||
|
||||
void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val);
|
||||
void dac_enable_channel(const dac_dev *dev, uint8 channel);
|
||||
void dac_disable_channel(const dac_dev *dev, uint8 channel);
|
||||
void dac_enable_buffer(const dac_dev *dev, uint32 flags, int status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* @file delay.h
|
||||
* @brief Delay implementation
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "stm32.h"
|
||||
|
||||
#ifndef _DELAY_H_
|
||||
#define _DELAY_H_
|
||||
|
||||
/**
|
||||
* @brief Delay the given number of microseconds.
|
||||
*
|
||||
* @param us Number of microseconds to delay.
|
||||
*/
|
||||
static inline void delay_us(uint32 us) {
|
||||
us *= STM32_DELAY_US_MULT;
|
||||
|
||||
/* 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");
|
||||
}
|
||||
|
||||
static inline void delay_ns100(uint32 us) {
|
||||
us *= STM32_DELAY_US_MULT;
|
||||
us /= 10;
|
||||
|
||||
/* 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");
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file dma.c
|
||||
* @brief DMA initialization routine
|
||||
*/
|
||||
|
||||
// #ifdef STM32F2
|
||||
// #include "dmaF2.c"
|
||||
// #else
|
||||
// #include "dmaF1.c"
|
||||
// #endif
|
|
@ -0,0 +1,37 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file dma.h
|
||||
*
|
||||
* @brief Direct Memory Access peripheral support
|
||||
*/
|
||||
|
||||
#ifdef STM32F2
|
||||
#include "dmaF2.h"
|
||||
#else
|
||||
#include "dmaF1.h"
|
||||
#endif
|
|
@ -0,0 +1,383 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef STM32F1
|
||||
|
||||
/**
|
||||
* @file dma.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
||||
* Original implementation by Michael Hope
|
||||
* @brief Direct Memory Access peripheral support
|
||||
*/
|
||||
|
||||
#include "dma.h"
|
||||
#include "bitband.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static dma_dev dma1 = {
|
||||
.regs = DMA1_BASE,
|
||||
.clk_id = RCC_DMA1,
|
||||
.handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH2 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH3 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH4 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH5 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH6 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH7 }}
|
||||
};
|
||||
/** DMA1 device */
|
||||
dma_dev *DMA1 = &dma1;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
static dma_dev dma2 = {
|
||||
.regs = DMA2_BASE,
|
||||
.clk_id = RCC_DMA2,
|
||||
.handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH2 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH3 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }} /* !@#$ */
|
||||
};
|
||||
/** DMA2 device */
|
||||
dma_dev *DMA2 = &dma2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize a DMA device.
|
||||
* @param dev Device to initialize.
|
||||
*/
|
||||
void dma_init(dma_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set up a DMA transfer.
|
||||
*
|
||||
* The channel will be disabled before being reconfigured. The
|
||||
* transfer will have low priority by default. You may choose another
|
||||
* priority before the transfer begins using dma_set_priority(), as
|
||||
* well as performing any other configuration you desire. When the
|
||||
* channel is configured to your liking, enable it using dma_enable().
|
||||
*
|
||||
* @param dev DMA device.
|
||||
* @param channel DMA channel.
|
||||
* @param peripheral_address Base address of peripheral data register
|
||||
* involved in the transfer.
|
||||
* @param peripheral_size Peripheral data transfer size.
|
||||
* @param memory_address Base memory address involved in the transfer.
|
||||
* @param memory_size Memory data transfer size.
|
||||
* @param mode Logical OR of dma_mode_flags
|
||||
* @sideeffect Disables the given DMA channel.
|
||||
* @see dma_xfer_size
|
||||
* @see dma_mode_flags
|
||||
* @see dma_set_num_transfers()
|
||||
* @see dma_set_priority()
|
||||
* @see dma_attach_interrupt()
|
||||
* @see dma_enable()
|
||||
*/
|
||||
void dma_setup_transfer(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
__io void *peripheral_address,
|
||||
dma_xfer_size peripheral_size,
|
||||
__io void *memory_address,
|
||||
dma_xfer_size memory_size,
|
||||
uint32 mode) {
|
||||
dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel);
|
||||
|
||||
dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */
|
||||
channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode;
|
||||
channel_regs->CMAR = (uint32)memory_address;
|
||||
channel_regs->CPAR = (uint32)peripheral_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the number of data to be transferred on a DMA channel.
|
||||
*
|
||||
* You may not call this function while the channel is enabled.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel Channel through which the transfer occurs.
|
||||
* @param num_transfers
|
||||
*/
|
||||
void dma_set_num_transfers(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
uint16 num_transfers) {
|
||||
dma_channel_reg_map *channel_regs;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
channel_regs = dma_channel_regs(dev, channel);
|
||||
channel_regs->CNDTR = num_transfers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the priority of a DMA transfer.
|
||||
*
|
||||
* You may not call this function while the channel is enabled.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel DMA channel
|
||||
* @param priority priority to set.
|
||||
*/
|
||||
void dma_set_priority(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
dma_priority priority) {
|
||||
dma_channel_reg_map *channel_regs;
|
||||
uint32 ccr;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
channel_regs = dma_channel_regs(dev, channel);
|
||||
ccr = channel_regs->CCR;
|
||||
ccr &= ~DMA_CCR_PL;
|
||||
ccr |= priority;
|
||||
channel_regs->CCR = ccr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach an interrupt to a DMA transfer.
|
||||
*
|
||||
* Interrupts are enabled using appropriate mode flags in
|
||||
* dma_setup_transfer().
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel Channel to attach handler to
|
||||
* @param handler Interrupt handler to call when channel interrupt fires.
|
||||
* @see dma_setup_transfer()
|
||||
* @see dma_get_irq_cause()
|
||||
* @see dma_detach_interrupt()
|
||||
*/
|
||||
void dma_attach_interrupt(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
void (*handler)(void)) {
|
||||
dev->handlers[channel - 1].handler = handler;
|
||||
nvic_irq_enable(dev->handlers[channel - 1].irq_line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach a DMA transfer interrupt handler.
|
||||
*
|
||||
* After calling this function, the given channel's interrupts will be
|
||||
* disabled.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel Channel whose handler to detach
|
||||
* @sideeffect Clears interrupt enable bits in the channel's CCR register.
|
||||
* @see dma_attach_interrupt()
|
||||
*/
|
||||
void dma_detach_interrupt(dma_dev *dev, dma_channel channel) {
|
||||
/* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */
|
||||
dma_channel_regs(dev, channel)->CCR &= ~0xF;
|
||||
dev->handlers[channel - 1].handler = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discover the reason why a DMA interrupt was called.
|
||||
*
|
||||
* You may only call this function within an attached interrupt
|
||||
* handler for the given channel.
|
||||
*
|
||||
* This function resets the internal DMA register state which encodes
|
||||
* the cause of the interrupt; consequently, it can only be called
|
||||
* once per interrupt handler invocation.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel Channel whose interrupt is being handled.
|
||||
* @return Reason why the interrupt fired.
|
||||
* @sideeffect Clears channel status flags in dev->regs->ISR.
|
||||
* @see dma_attach_interrupt()
|
||||
* @see dma_irq_cause
|
||||
*/
|
||||
dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) {
|
||||
uint8 status_bits = dma_get_isr_bits(dev, channel);
|
||||
|
||||
/* If the channel global interrupt flag is cleared, then
|
||||
* something's very wrong. */
|
||||
ASSERT(status_bits & BIT(0));
|
||||
|
||||
dma_clear_isr_bits(dev, channel);
|
||||
|
||||
/* ISR flags get set even if the corresponding interrupt enable
|
||||
* bits in the channel's configuration register are cleared, so we
|
||||
* can't use a switch here.
|
||||
*
|
||||
* Don't change the order of these if statements. */
|
||||
if (status_bits & BIT(3)) {
|
||||
return DMA_TRANSFER_ERROR;
|
||||
} else if (status_bits & BIT(1)) {
|
||||
return DMA_TRANSFER_COMPLETE;
|
||||
} else if (status_bits & BIT(2)) {
|
||||
return DMA_TRANSFER_HALF_COMPLETE;
|
||||
} else if (status_bits & BIT(0)) {
|
||||
/* Shouldn't happen (unless someone messed up an IFCR write). */
|
||||
throb();
|
||||
}
|
||||
#if DEBUG_LEVEL < DEBUG_ALL
|
||||
else {
|
||||
/* We shouldn't have been called, but the debug level is too
|
||||
* low for the above ASSERT() to have had any effect. In
|
||||
* order to fail fast, mimic the DMA controller's behavior
|
||||
* when an error occurs. */
|
||||
dma_disable(dev, channel);
|
||||
}
|
||||
#endif
|
||||
return DMA_TRANSFER_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a DMA channel.
|
||||
* @param dev DMA device
|
||||
* @param channel Channel to enable
|
||||
*/
|
||||
void dma_enable(dma_dev *dev, dma_channel channel) {
|
||||
dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel);
|
||||
bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a DMA channel.
|
||||
* @param dev DMA device
|
||||
* @param channel Channel to disable
|
||||
*/
|
||||
void dma_disable(dma_dev *dev, dma_channel channel) {
|
||||
dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel);
|
||||
bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the base memory address where data will be read from or
|
||||
* written to.
|
||||
*
|
||||
* You must not call this function while the channel is enabled.
|
||||
*
|
||||
* If the DMA memory size is 16 bits, the address is automatically
|
||||
* aligned to a half-word. If the DMA memory size is 32 bits, the
|
||||
* address is aligned to a word.
|
||||
*
|
||||
* @param dev DMA Device
|
||||
* @param channel Channel whose base memory address to set.
|
||||
* @param addr Memory base address to use.
|
||||
*/
|
||||
void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) {
|
||||
dma_channel_reg_map *chan_regs;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
chan_regs = dma_channel_regs(dev, channel);
|
||||
chan_regs->CMAR = (uint32)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the base peripheral address where data will be read from
|
||||
* or written to.
|
||||
*
|
||||
* You must not call this function while the channel is enabled.
|
||||
*
|
||||
* If the DMA peripheral size is 16 bits, the address is automatically
|
||||
* aligned to a half-word. If the DMA peripheral size is 32 bits, the
|
||||
* address is aligned to a word.
|
||||
*
|
||||
* @param dev DMA Device
|
||||
* @param channel Channel whose peripheral data register base address to set.
|
||||
* @param addr Peripheral memory base address to use.
|
||||
*/
|
||||
void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) {
|
||||
dma_channel_reg_map *chan_regs;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
chan_regs = dma_channel_regs(dev, channel);
|
||||
chan_regs->CPAR = (uint32)addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handlers
|
||||
*/
|
||||
|
||||
static inline void dispatch_handler(dma_dev *dev, dma_channel channel) {
|
||||
void (*handler)(void) = dev->handlers[channel - 1].handler;
|
||||
if (handler) {
|
||||
handler();
|
||||
dma_clear_isr_bits(dev, channel); /* in case handler doesn't */
|
||||
}
|
||||
}
|
||||
|
||||
void __irq_dma1_channel1(void) {
|
||||
dispatch_handler(DMA1, DMA_CH1);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel2(void) {
|
||||
dispatch_handler(DMA1, DMA_CH2);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel3(void) {
|
||||
dispatch_handler(DMA1, DMA_CH3);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel4(void) {
|
||||
dispatch_handler(DMA1, DMA_CH4);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel5(void) {
|
||||
dispatch_handler(DMA1, DMA_CH5);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel6(void) {
|
||||
dispatch_handler(DMA1, DMA_CH6);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel7(void) {
|
||||
dispatch_handler(DMA1, DMA_CH7);
|
||||
}
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
void __irq_dma2_channel1(void) {
|
||||
dispatch_handler(DMA2, DMA_CH1);
|
||||
}
|
||||
|
||||
void __irq_dma2_channel2(void) {
|
||||
dispatch_handler(DMA2, DMA_CH2);
|
||||
}
|
||||
|
||||
void __irq_dma2_channel3(void) {
|
||||
dispatch_handler(DMA2, DMA_CH3);
|
||||
}
|
||||
|
||||
void __irq_dma2_channel4_5(void) {
|
||||
dispatch_handler(DMA2, DMA_CH4);
|
||||
dispatch_handler(DMA2, DMA_CH5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,453 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* 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 dma.h
|
||||
*
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
||||
* Original implementation by Michael Hope
|
||||
*
|
||||
* @brief Direct Memory Access peripheral support
|
||||
*/
|
||||
|
||||
/*
|
||||
* See /notes/dma.txt for more information.
|
||||
*/
|
||||
|
||||
#ifndef _DMA_H_
|
||||
#define _DMA_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register maps
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA register map type.
|
||||
*
|
||||
* Note that DMA controller 2 (register map base pointer DMA2_BASE)
|
||||
* only supports channels 1--5.
|
||||
*/
|
||||
typedef struct dma_reg_map {
|
||||
__io uint32 ISR; /**< Interrupt status register */
|
||||
__io uint32 IFCR; /**< Interrupt flag clear register */
|
||||
__io uint32 CCR1; /**< Channel 1 configuration register */
|
||||
__io uint32 CNDTR1; /**< Channel 1 number of data register */
|
||||
__io uint32 CPAR1; /**< Channel 1 peripheral address register */
|
||||
__io uint32 CMAR1; /**< Channel 1 memory address register */
|
||||
const uint32 RESERVED1; /**< Reserved. */
|
||||
__io uint32 CCR2; /**< Channel 2 configuration register */
|
||||
__io uint32 CNDTR2; /**< Channel 2 number of data register */
|
||||
__io uint32 CPAR2; /**< Channel 2 peripheral address register */
|
||||
__io uint32 CMAR2; /**< Channel 2 memory address register */
|
||||
const uint32 RESERVED2; /**< Reserved. */
|
||||
__io uint32 CCR3; /**< Channel 3 configuration register */
|
||||
__io uint32 CNDTR3; /**< Channel 3 number of data register */
|
||||
__io uint32 CPAR3; /**< Channel 3 peripheral address register */
|
||||
__io uint32 CMAR3; /**< Channel 3 memory address register */
|
||||
const uint32 RESERVED3; /**< Reserved. */
|
||||
__io uint32 CCR4; /**< Channel 4 configuration register */
|
||||
__io uint32 CNDTR4; /**< Channel 4 number of data register */
|
||||
__io uint32 CPAR4; /**< Channel 4 peripheral address register */
|
||||
__io uint32 CMAR4; /**< Channel 4 memory address register */
|
||||
const uint32 RESERVED4; /**< Reserved. */
|
||||
__io uint32 CCR5; /**< Channel 5 configuration register */
|
||||
__io uint32 CNDTR5; /**< Channel 5 number of data register */
|
||||
__io uint32 CPAR5; /**< Channel 5 peripheral address register */
|
||||
__io uint32 CMAR5; /**< Channel 5 memory address register */
|
||||
const uint32 RESERVED5; /**< Reserved. */
|
||||
__io uint32 CCR6; /**< Channel 6 configuration register */
|
||||
__io uint32 CNDTR6; /**< Channel 6 number of data register */
|
||||
__io uint32 CPAR6; /**< Channel 6 peripheral address register */
|
||||
__io uint32 CMAR6; /**< Channel 6 memory address register */
|
||||
const uint32 RESERVED6; /**< Reserved. */
|
||||
__io uint32 CCR7; /**< Channel 7 configuration register */
|
||||
__io uint32 CNDTR7; /**< Channel 7 number of data register */
|
||||
__io uint32 CPAR7; /**< Channel 7 peripheral address register */
|
||||
__io uint32 CMAR7; /**< Channel 7 memory address register */
|
||||
const uint32 RESERVED7; /**< Reserved. */
|
||||
} dma_reg_map;
|
||||
|
||||
/** DMA controller 1 register map base pointer */
|
||||
#define DMA1_BASE ((struct dma_reg_map*)0x40020000)
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
/** DMA controller 2 register map base pointer */
|
||||
#define DMA2_BASE ((struct dma_reg_map*)0x40020400)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Interrupt status register */
|
||||
|
||||
#define DMA_ISR_TEIF7_BIT 27
|
||||
#define DMA_ISR_HTIF7_BIT 26
|
||||
#define DMA_ISR_TCIF7_BIT 25
|
||||
#define DMA_ISR_GIF7_BIT 24
|
||||
#define DMA_ISR_TEIF6_BIT 23
|
||||
#define DMA_ISR_HTIF6_BIT 22
|
||||
#define DMA_ISR_TCIF6_BIT 21
|
||||
#define DMA_ISR_GIF6_BIT 20
|
||||
#define DMA_ISR_TEIF5_BIT 19
|
||||
#define DMA_ISR_HTIF5_BIT 18
|
||||
#define DMA_ISR_TCIF5_BIT 17
|
||||
#define DMA_ISR_GIF5_BIT 16
|
||||
#define DMA_ISR_TEIF4_BIT 15
|
||||
#define DMA_ISR_HTIF4_BIT 14
|
||||
#define DMA_ISR_TCIF4_BIT 13
|
||||
#define DMA_ISR_GIF4_BIT 12
|
||||
#define DMA_ISR_TEIF3_BIT 11
|
||||
#define DMA_ISR_HTIF3_BIT 10
|
||||
#define DMA_ISR_TCIF3_BIT 9
|
||||
#define DMA_ISR_GIF3_BIT 8
|
||||
#define DMA_ISR_TEIF2_BIT 7
|
||||
#define DMA_ISR_HTIF2_BIT 6
|
||||
#define DMA_ISR_TCIF2_BIT 5
|
||||
#define DMA_ISR_GIF2_BIT 4
|
||||
#define DMA_ISR_TEIF1_BIT 3
|
||||
#define DMA_ISR_HTIF1_BIT 2
|
||||
#define DMA_ISR_TCIF1_BIT 1
|
||||
#define DMA_ISR_GIF1_BIT 0
|
||||
|
||||
#define DMA_ISR_TEIF7 BIT(DMA_ISR_TEIF7_BIT)
|
||||
#define DMA_ISR_HTIF7 BIT(DMA_ISR_HTIF7_BIT)
|
||||
#define DMA_ISR_TCIF7 BIT(DMA_ISR_TCIF7_BIT)
|
||||
#define DMA_ISR_GIF7 BIT(DMA_ISR_GIF7_BIT)
|
||||
#define DMA_ISR_TEIF6 BIT(DMA_ISR_TEIF6_BIT)
|
||||
#define DMA_ISR_HTIF6 BIT(DMA_ISR_HTIF6_BIT)
|
||||
#define DMA_ISR_TCIF6 BIT(DMA_ISR_TCIF6_BIT)
|
||||
#define DMA_ISR_GIF6 BIT(DMA_ISR_GIF6_BIT)
|
||||
#define DMA_ISR_TEIF5 BIT(DMA_ISR_TEIF5_BIT)
|
||||
#define DMA_ISR_HTIF5 BIT(DMA_ISR_HTIF5_BIT)
|
||||
#define DMA_ISR_TCIF5 BIT(DMA_ISR_TCIF5_BIT)
|
||||
#define DMA_ISR_GIF5 BIT(DMA_ISR_GIF5_BIT)
|
||||
#define DMA_ISR_TEIF4 BIT(DMA_ISR_TEIF4_BIT)
|
||||
#define DMA_ISR_HTIF4 BIT(DMA_ISR_HTIF4_BIT)
|
||||
#define DMA_ISR_TCIF4 BIT(DMA_ISR_TCIF4_BIT)
|
||||
#define DMA_ISR_GIF4 BIT(DMA_ISR_GIF4_BIT)
|
||||
#define DMA_ISR_TEIF3 BIT(DMA_ISR_TEIF3_BIT)
|
||||
#define DMA_ISR_HTIF3 BIT(DMA_ISR_HTIF3_BIT)
|
||||
#define DMA_ISR_TCIF3 BIT(DMA_ISR_TCIF3_BIT)
|
||||
#define DMA_ISR_GIF3 BIT(DMA_ISR_GIF3_BIT)
|
||||
#define DMA_ISR_TEIF2 BIT(DMA_ISR_TEIF2_BIT)
|
||||
#define DMA_ISR_HTIF2 BIT(DMA_ISR_HTIF2_BIT)
|
||||
#define DMA_ISR_TCIF2 BIT(DMA_ISR_TCIF2_BIT)
|
||||
#define DMA_ISR_GIF2 BIT(DMA_ISR_GIF2_BIT)
|
||||
#define DMA_ISR_TEIF1 BIT(DMA_ISR_TEIF1_BIT)
|
||||
#define DMA_ISR_HTIF1 BIT(DMA_ISR_HTIF1_BIT)
|
||||
#define DMA_ISR_TCIF1 BIT(DMA_ISR_TCIF1_BIT)
|
||||
#define DMA_ISR_GIF1 BIT(DMA_ISR_GIF1_BIT)
|
||||
|
||||
/* Interrupt flag clear register */
|
||||
|
||||
#define DMA_IFCR_CTEIF7_BIT 27
|
||||
#define DMA_IFCR_CHTIF7_BIT 26
|
||||
#define DMA_IFCR_CTCIF7_BIT 25
|
||||
#define DMA_IFCR_CGIF7_BIT 24
|
||||
#define DMA_IFCR_CTEIF6_BIT 23
|
||||
#define DMA_IFCR_CHTIF6_BIT 22
|
||||
#define DMA_IFCR_CTCIF6_BIT 21
|
||||
#define DMA_IFCR_CGIF6_BIT 20
|
||||
#define DMA_IFCR_CTEIF5_BIT 19
|
||||
#define DMA_IFCR_CHTIF5_BIT 18
|
||||
#define DMA_IFCR_CTCIF5_BIT 17
|
||||
#define DMA_IFCR_CGIF5_BIT 16
|
||||
#define DMA_IFCR_CTEIF4_BIT 15
|
||||
#define DMA_IFCR_CHTIF4_BIT 14
|
||||
#define DMA_IFCR_CTCIF4_BIT 13
|
||||
#define DMA_IFCR_CGIF4_BIT 12
|
||||
#define DMA_IFCR_CTEIF3_BIT 11
|
||||
#define DMA_IFCR_CHTIF3_BIT 10
|
||||
#define DMA_IFCR_CTCIF3_BIT 9
|
||||
#define DMA_IFCR_CGIF3_BIT 8
|
||||
#define DMA_IFCR_CTEIF2_BIT 7
|
||||
#define DMA_IFCR_CHTIF2_BIT 6
|
||||
#define DMA_IFCR_CTCIF2_BIT 5
|
||||
#define DMA_IFCR_CGIF2_BIT 4
|
||||
#define DMA_IFCR_CTEIF1_BIT 3
|
||||
#define DMA_IFCR_CHTIF1_BIT 2
|
||||
#define DMA_IFCR_CTCIF1_BIT 1
|
||||
#define DMA_IFCR_CGIF1_BIT 0
|
||||
|
||||
#define DMA_IFCR_CTEIF7 BIT(DMA_IFCR_CTEIF7_BIT)
|
||||
#define DMA_IFCR_CHTIF7 BIT(DMA_IFCR_CHTIF7_BIT)
|
||||
#define DMA_IFCR_CTCIF7 BIT(DMA_IFCR_CTCIF7_BIT)
|
||||
#define DMA_IFCR_CGIF7 BIT(DMA_IFCR_CGIF7_BIT)
|
||||
#define DMA_IFCR_CTEIF6 BIT(DMA_IFCR_CTEIF6_BIT)
|
||||
#define DMA_IFCR_CHTIF6 BIT(DMA_IFCR_CHTIF6_BIT)
|
||||
#define DMA_IFCR_CTCIF6 BIT(DMA_IFCR_CTCIF6_BIT)
|
||||
#define DMA_IFCR_CGIF6 BIT(DMA_IFCR_CGIF6_BIT)
|
||||
#define DMA_IFCR_CTEIF5 BIT(DMA_IFCR_CTEIF5_BIT)
|
||||
#define DMA_IFCR_CHTIF5 BIT(DMA_IFCR_CHTIF5_BIT)
|
||||
#define DMA_IFCR_CTCIF5 BIT(DMA_IFCR_CTCIF5_BIT)
|
||||
#define DMA_IFCR_CGIF5 BIT(DMA_IFCR_CGIF5_BIT)
|
||||
#define DMA_IFCR_CTEIF4 BIT(DMA_IFCR_CTEIF4_BIT)
|
||||
#define DMA_IFCR_CHTIF4 BIT(DMA_IFCR_CHTIF4_BIT)
|
||||
#define DMA_IFCR_CTCIF4 BIT(DMA_IFCR_CTCIF4_BIT)
|
||||
#define DMA_IFCR_CGIF4 BIT(DMA_IFCR_CGIF4_BIT)
|
||||
#define DMA_IFCR_CTEIF3 BIT(DMA_IFCR_CTEIF3_BIT)
|
||||
#define DMA_IFCR_CHTIF3 BIT(DMA_IFCR_CHTIF3_BIT)
|
||||
#define DMA_IFCR_CTCIF3 BIT(DMA_IFCR_CTCIF3_BIT)
|
||||
#define DMA_IFCR_CGIF3 BIT(DMA_IFCR_CGIF3_BIT)
|
||||
#define DMA_IFCR_CTEIF2 BIT(DMA_IFCR_CTEIF2_BIT)
|
||||
#define DMA_IFCR_CHTIF2 BIT(DMA_IFCR_CHTIF2_BIT)
|
||||
#define DMA_IFCR_CTCIF2 BIT(DMA_IFCR_CTCIF2_BIT)
|
||||
#define DMA_IFCR_CGIF2 BIT(DMA_IFCR_CGIF2_BIT)
|
||||
#define DMA_IFCR_CTEIF1 BIT(DMA_IFCR_CTEIF1_BIT)
|
||||
#define DMA_IFCR_CHTIF1 BIT(DMA_IFCR_CHTIF1_BIT)
|
||||
#define DMA_IFCR_CTCIF1 BIT(DMA_IFCR_CTCIF1_BIT)
|
||||
#define DMA_IFCR_CGIF1 BIT(DMA_IFCR_CGIF1_BIT)
|
||||
|
||||
/* Channel configuration register */
|
||||
|
||||
#define DMA_CCR_MEM2MEM_BIT 14
|
||||
#define DMA_CCR_MINC_BIT 7
|
||||
#define DMA_CCR_PINC_BIT 6
|
||||
#define DMA_CCR_CIRC_BIT 5
|
||||
#define DMA_CCR_DIR_BIT 4
|
||||
#define DMA_CCR_TEIE_BIT 3
|
||||
#define DMA_CCR_HTIE_BIT 2
|
||||
#define DMA_CCR_TCIE_BIT 1
|
||||
#define DMA_CCR_EN_BIT 0
|
||||
|
||||
#define DMA_CCR_MEM2MEM BIT(DMA_CCR_MEM2MEM_BIT)
|
||||
#define DMA_CCR_PL (0x3 << 12)
|
||||
#define DMA_CCR_PL_LOW (0x0 << 12)
|
||||
#define DMA_CCR_PL_MEDIUM (0x1 << 12)
|
||||
#define DMA_CCR_PL_HIGH (0x2 << 12)
|
||||
#define DMA_CCR_PL_VERY_HIGH (0x3 << 12)
|
||||
#define DMA_CCR_MSIZE (0x3 << 10)
|
||||
#define DMA_CCR_MSIZE_8BITS (0x0 << 10)
|
||||
#define DMA_CCR_MSIZE_16BITS (0x1 << 10)
|
||||
#define DMA_CCR_MSIZE_32BITS (0x2 << 10)
|
||||
#define DMA_CCR_PSIZE (0x3 << 8)
|
||||
#define DMA_CCR_PSIZE_8BITS (0x0 << 8)
|
||||
#define DMA_CCR_PSIZE_16BITS (0x1 << 8)
|
||||
#define DMA_CCR_PSIZE_32BITS (0x2 << 8)
|
||||
#define DMA_CCR_MINC BIT(DMA_CCR_MINC_BIT)
|
||||
#define DMA_CCR_PINC BIT(DMA_CCR_PINC_BIT)
|
||||
#define DMA_CCR_CIRC BIT(DMA_CCR_CIRC_BIT)
|
||||
#define DMA_CCR_DIR BIT(DMA_CCR_DIR_BIT)
|
||||
#define DMA_CCR_TEIE BIT(DMA_CCR_TEIE_BIT)
|
||||
#define DMA_CCR_HTIE BIT(DMA_CCR_HTIE_BIT)
|
||||
#define DMA_CCR_TCIE BIT(DMA_CCR_TCIE_BIT)
|
||||
#define DMA_CCR_EN BIT(DMA_CCR_EN_BIT)
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
/** Encapsulates state related to a DMA channel interrupt. */
|
||||
typedef struct dma_handler_config {
|
||||
void (*handler)(void); /**< User-specified channel interrupt
|
||||
handler */
|
||||
nvic_irq_num irq_line; /**< Channel's NVIC interrupt number */
|
||||
} dma_handler_config;
|
||||
|
||||
/** DMA device type */
|
||||
typedef struct dma_dev {
|
||||
dma_reg_map *regs; /**< Register map */
|
||||
rcc_clk_id clk_id; /**< Clock ID */
|
||||
dma_handler_config handlers[]; /**<
|
||||
* @brief IRQ handlers and NVIC numbers.
|
||||
*
|
||||
* @see dma_attach_interrupt()
|
||||
* @see dma_detach_interrupt()
|
||||
*/
|
||||
} dma_dev;
|
||||
|
||||
extern dma_dev *DMA1;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
extern dma_dev *DMA2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convenience functions
|
||||
*/
|
||||
|
||||
void dma_init(dma_dev *dev);
|
||||
|
||||
/** Flags for DMA transfer configuration. */
|
||||
typedef enum dma_mode_flags {
|
||||
DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */
|
||||
DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */
|
||||
DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */
|
||||
DMA_CIRC_MODE = 1 << 5, /**< Circular mode */
|
||||
DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */
|
||||
DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */
|
||||
DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */
|
||||
DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */
|
||||
} dma_mode_flags;
|
||||
|
||||
/** Source and destination transfer sizes. */
|
||||
typedef enum dma_xfer_size {
|
||||
DMA_SIZE_8BITS = 0, /**< 8-bit transfers */
|
||||
DMA_SIZE_16BITS = 1, /**< 16-bit transfers */
|
||||
DMA_SIZE_32BITS = 2 /**< 32-bit transfers */
|
||||
} dma_xfer_size;
|
||||
|
||||
/** DMA channel */
|
||||
typedef enum dma_channel {
|
||||
DMA_CH1 = 1, /**< Channel 1 */
|
||||
DMA_CH2 = 2, /**< Channel 2 */
|
||||
DMA_CH3 = 3, /**< Channel 3 */
|
||||
DMA_CH4 = 4, /**< Channel 4 */
|
||||
DMA_CH5 = 5, /**< Channel 5 */
|
||||
DMA_CH6 = 6, /**< Channel 6 */
|
||||
DMA_CH7 = 7, /**< Channel 7 */
|
||||
} dma_channel;
|
||||
|
||||
void dma_setup_transfer(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
__io void *peripheral_address,
|
||||
dma_xfer_size peripheral_size,
|
||||
__io void *memory_address,
|
||||
dma_xfer_size memory_size,
|
||||
uint32 mode);
|
||||
|
||||
void dma_set_num_transfers(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
uint16 num_transfers);
|
||||
|
||||
/** DMA transfer priority. */
|
||||
typedef enum dma_priority {
|
||||
DMA_PRIORITY_LOW = DMA_CCR_PL_LOW, /**< Low priority */
|
||||
DMA_PRIORITY_MEDIUM = DMA_CCR_PL_MEDIUM, /**< Medium priority */
|
||||
DMA_PRIORITY_HIGH = DMA_CCR_PL_HIGH, /**< High priority */
|
||||
DMA_PRIORITY_VERY_HIGH = DMA_CCR_PL_VERY_HIGH /**< Very high priority */
|
||||
} dma_priority;
|
||||
|
||||
void dma_set_priority(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
dma_priority priority);
|
||||
|
||||
void dma_attach_interrupt(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
void (*handler)(void));
|
||||
void dma_detach_interrupt(dma_dev *dev, dma_channel channel);
|
||||
|
||||
/**
|
||||
* Encodes the reason why a DMA interrupt was called.
|
||||
* @see dma_get_irq_cause()
|
||||
*/
|
||||
typedef enum dma_irq_cause {
|
||||
DMA_TRANSFER_COMPLETE, /**< Transfer is complete. */
|
||||
DMA_TRANSFER_HALF_COMPLETE, /**< Transfer is half complete. */
|
||||
DMA_TRANSFER_ERROR, /**< Error occurred during transfer. */
|
||||
} dma_irq_cause;
|
||||
|
||||
dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel);
|
||||
|
||||
void dma_enable(dma_dev *dev, dma_channel channel);
|
||||
void dma_disable(dma_dev *dev, dma_channel channel);
|
||||
|
||||
void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *address);
|
||||
void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *address);
|
||||
|
||||
/**
|
||||
* @brief DMA channel register map type.
|
||||
*
|
||||
* Provides access to an individual channel's registers.
|
||||
*/
|
||||
typedef struct dma_channel_reg_map {
|
||||
__io uint32 CCR; /**< Channel configuration register */
|
||||
__io uint32 CNDTR; /**< Channel number of data register */
|
||||
__io uint32 CPAR; /**< Channel peripheral address register */
|
||||
__io uint32 CMAR; /**< Channel memory address register */
|
||||
} dma_channel_reg_map;
|
||||
|
||||
#define DMA_CHANNEL_NREGS 5
|
||||
|
||||
/**
|
||||
* @brief Obtain a pointer to an individual DMA channel's registers.
|
||||
*
|
||||
* For example, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel DMA channel whose channel register map to obtain.
|
||||
*/
|
||||
static inline dma_channel_reg_map* dma_channel_regs(dma_dev *dev,
|
||||
dma_channel channel) {
|
||||
__io uint32 *ccr1 = &dev->regs->CCR1;
|
||||
return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (channel - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a DMA channel is enabled
|
||||
* @param dev DMA device
|
||||
* @param channel Channel whose enabled bit to check.
|
||||
*/
|
||||
static inline uint8 dma_is_channel_enabled(dma_dev *dev, dma_channel channel) {
|
||||
return (uint8)(dma_channel_regs(dev, channel)->CCR & DMA_CCR_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the ISR status bits for a DMA channel.
|
||||
*
|
||||
* The bits are returned right-aligned, in the following order:
|
||||
* transfer error flag, half-transfer flag, transfer complete flag,
|
||||
* global interrupt flag.
|
||||
*
|
||||
* If you're attempting to figure out why a DMA interrupt fired; you
|
||||
* may find dma_get_irq_cause() more convenient.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel Channel whose ISR bits to return.
|
||||
* @see dma_get_irq_cause().
|
||||
*/
|
||||
static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_channel channel) {
|
||||
uint8 shift = (channel - 1) * 4;
|
||||
return (dev->regs->ISR >> shift) & 0xF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the ISR status bits for a given DMA channel.
|
||||
*
|
||||
* If you're attempting to clean up after yourself in a DMA interrupt,
|
||||
* you may find dma_get_irq_cause() more convenient.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param channel Channel whose ISR bits to clear.
|
||||
* @see dma_get_irq_cause()
|
||||
*/
|
||||
static inline void dma_clear_isr_bits(dma_dev *dev, dma_channel channel) {
|
||||
dev->regs->IFCR = BIT(4 * (channel - 1));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,241 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef STM32F2
|
||||
|
||||
/**
|
||||
* @file dmaF2.c
|
||||
* @brief Direct Memory Access peripheral support
|
||||
*/
|
||||
|
||||
#include "dma.h"
|
||||
#include "bitband.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static dma_dev dma1 = {
|
||||
.regs = DMA1_BASE,
|
||||
.clk_id = RCC_DMA1,
|
||||
.handlers = {{ .handler = NULL, .irq_line = 11 },
|
||||
{ .handler = NULL, .irq_line = 12 },
|
||||
{ .handler = NULL, .irq_line = 13 },
|
||||
{ .handler = NULL, .irq_line = 14 },
|
||||
{ .handler = NULL, .irq_line = 15 },
|
||||
{ .handler = NULL, .irq_line = 16 },
|
||||
{ .handler = NULL, .irq_line = 17 },
|
||||
{ .handler = NULL, .irq_line = 47 }}
|
||||
};
|
||||
/** DMA1 device */
|
||||
dma_dev *DMA1 = &dma1;
|
||||
|
||||
static dma_dev dma2 = {
|
||||
.regs = DMA2_BASE,
|
||||
.clk_id = RCC_DMA2,
|
||||
.handlers = {{ .handler = NULL, .irq_line = 56 },
|
||||
{ .handler = NULL, .irq_line = 57 },
|
||||
{ .handler = NULL, .irq_line = 58 },
|
||||
{ .handler = NULL, .irq_line = 59 },
|
||||
{ .handler = NULL, .irq_line = 60 },
|
||||
{ .handler = NULL, .irq_line = 68 },
|
||||
{ .handler = NULL, .irq_line = 69 },
|
||||
{ .handler = NULL, .irq_line = 70 }} /* !@#$ */
|
||||
};
|
||||
/** DMA2 device */
|
||||
dma_dev *DMA2 = &dma2;
|
||||
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize a DMA device.
|
||||
* @param dev Device to initialize.
|
||||
*/
|
||||
void dma_init(dma_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach an interrupt to a DMA transfer.
|
||||
*
|
||||
* Interrupts are enabled using appropriate mode flags in
|
||||
* dma_setup_transfer().
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param stream Stream to attach handler to
|
||||
* @param handler Interrupt handler to call when channel interrupt fires.
|
||||
* @see dma_setup_transfer()
|
||||
* @see dma_detach_interrupt()
|
||||
*/
|
||||
void dma_attach_interrupt(dma_dev *dev,
|
||||
dma_stream stream,
|
||||
void (*handler)(void)) {
|
||||
dev->handlers[stream].handler = handler;
|
||||
nvic_irq_enable(dev->handlers[stream].irq_line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach a DMA transfer interrupt handler.
|
||||
*
|
||||
* After calling this function, the given channel's interrupts will be
|
||||
* disabled.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param stream Stream whose handler to detach
|
||||
* @sideeffect Clears interrupt enable bits in the channel's CCR register.
|
||||
* @see dma_attach_interrupt()
|
||||
*/
|
||||
void dma_detach_interrupt(dma_dev *dev, dma_stream stream) {
|
||||
nvic_irq_disable(dev->handlers[stream].irq_line);
|
||||
dev->handlers[stream].handler = NULL;
|
||||
}
|
||||
|
||||
void dma_clear_isr_bits(dma_dev *dev, dma_stream stream) {
|
||||
switch (stream) {
|
||||
case 0:
|
||||
dev->regs->LIFCR|=0x0000003d;
|
||||
break;
|
||||
case 1:
|
||||
dev->regs->LIFCR|=0x00000f40;
|
||||
break;
|
||||
case 2:
|
||||
dev->regs->LIFCR|=0x003d0000;
|
||||
break;
|
||||
case 3:
|
||||
dev->regs->LIFCR|=0x0f400000;
|
||||
break;
|
||||
case 4:
|
||||
dev->regs->HIFCR|=0x0000003d;
|
||||
break;
|
||||
case 5:
|
||||
dev->regs->HIFCR|=0x00000f40;
|
||||
break;
|
||||
case 6:
|
||||
dev->regs->HIFCR|=0x003d0000;
|
||||
break;
|
||||
case 7:
|
||||
dev->regs->HIFCR|=0x0f400000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handlers
|
||||
*/
|
||||
|
||||
static inline void dispatch_handler(dma_dev *dev, dma_stream stream) {
|
||||
void (*handler)(void) = dev->handlers[stream].handler;
|
||||
if (handler) {
|
||||
handler();
|
||||
dma_clear_isr_bits(dev, stream); /* in case handler doesn't */
|
||||
}
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream0(void) {
|
||||
void __irq_dma1_channel1(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM0);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream1(void) {
|
||||
void __irq_dma1_channel2(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM1);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream2(void) {
|
||||
void __irq_dma1_channel3(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM2);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream3(void) {
|
||||
void __irq_dma1_channel4(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM3);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream4(void) {
|
||||
void __irq_dma1_channel5(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM4);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream5(void) {
|
||||
void __irq_dma1_channel6(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM5);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream6(void) {
|
||||
void __irq_dma1_channel7(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM6);
|
||||
}
|
||||
|
||||
//void __irq_dma1_stream7(void) {
|
||||
void __irq_adc3(void) {
|
||||
dispatch_handler(DMA1, DMA_STREAM7);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream0(void) {
|
||||
void __irq_dma2_channel1(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM0);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream1(void) {
|
||||
void __irq_dma2_channel2(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM1);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream2(void) {
|
||||
void __irq_dma2_channel3(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM2);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream3(void) {
|
||||
void __irq_dma2_channel4_5(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM3);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream4(void) {
|
||||
void __irq_DMA2_Stream4_IRQHandler(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM4);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream5(void) {
|
||||
void __irq_DMA2_Stream5_IRQHandler(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM5);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream6(void) {
|
||||
void __irq_DMA2_Stream6_IRQHandler(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM6);
|
||||
}
|
||||
|
||||
//void __irq_dma2_stream7(void) {
|
||||
void __irq_DMA2_Stream7_IRQHandler(void) {
|
||||
dispatch_handler(DMA2, DMA_STREAM7);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,270 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* 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 dma.h
|
||||
*
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
||||
* Original implementation by Michael Hope
|
||||
*
|
||||
* @brief Direct Memory Access peripheral support
|
||||
*/
|
||||
|
||||
/*
|
||||
* See /notes/dma.txt for more information.
|
||||
*/
|
||||
|
||||
#ifndef _DMA_H_
|
||||
#define _DMA_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register maps
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA stream type.
|
||||
*
|
||||
*/
|
||||
typedef struct dma_stream_t {
|
||||
__io uint32 CR; /**< Stream configuration register */
|
||||
__io uint32 NDTR; /**< Stream number of data register */
|
||||
__io uint32 PAR; /**< Stream peripheral address register */
|
||||
__io uint32 M0AR; /**< Stream memory address register 0 */
|
||||
__io uint32 M1AR; /**< Stream memory address register 1 */
|
||||
__io uint32 FCR; /**< Stream FIFO configuration register */
|
||||
} dma_stream_t;
|
||||
/**
|
||||
* @brief DMA register map type.
|
||||
*
|
||||
*/
|
||||
typedef struct dma_reg_map {
|
||||
__io uint32 LISR; /**< Low interrupt status register */
|
||||
__io uint32 HISR; /**< High interrupt status register */
|
||||
__io uint32 LIFCR; /**< Low interrupt flag clear register */
|
||||
__io uint32 HIFCR; /**< High interrupt flag clear register */
|
||||
dma_stream_t STREAM[8];
|
||||
} dma_reg_map;
|
||||
|
||||
/** DMA controller register map base pointers */
|
||||
#define DMA1_BASE ((struct dma_reg_map*)0x40026000)
|
||||
#define DMA2_BASE ((struct dma_reg_map*)0x40026400)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Channel configuration register */
|
||||
|
||||
#define DMA_CR_CH0 (0x0 << 25)
|
||||
#define DMA_CR_CH1 (0x1 << 25)
|
||||
#define DMA_CR_CH2 (0x2 << 25)
|
||||
#define DMA_CR_CH3 (0x3 << 25)
|
||||
#define DMA_CR_CH4 (0x4 << 25)
|
||||
#define DMA_CR_CH5 (0x5 << 25)
|
||||
#define DMA_CR_CH6 (0x6 << 25)
|
||||
#define DMA_CR_CH7 (0x7 << 25)
|
||||
#define DMA_CR_MBURST0 (0x0 << 23)
|
||||
#define DMA_CR_MBURST4 (0x1 << 23)
|
||||
#define DMA_CR_MBURST8 (0x2 << 23)
|
||||
#define DMA_CR_MBURST16 (0x3 << 23)
|
||||
#define DMA_CR_PBURST0 (0x0 << 21)
|
||||
#define DMA_CR_PBURST4 (0x1 << 21)
|
||||
#define DMA_CR_PBURST8 (0x2 << 21)
|
||||
#define DMA_CR_PBURST16 (0x3 << 21)
|
||||
#define DMA_CR_CT0 (0x0 << 19)
|
||||
#define DMA_CR_CT1 (0x1 << 19)
|
||||
#define DMA_CR_DBM (0x1 << 18)
|
||||
|
||||
#define DMA_CR_PL_LOW (0x0 << 16)
|
||||
#define DMA_CR_PL_MEDIUM (0x1 << 16)
|
||||
#define DMA_CR_PL_HIGH (0x2 << 16)
|
||||
#define DMA_CR_PL_VERY_HIGH (0x3 << 16)
|
||||
#define DMA_CR_PL_MASK (0x3 << 16)
|
||||
|
||||
#define DMA_CR_PINCOS (0x1 << 15)
|
||||
|
||||
#define DMA_CR_MSIZE_8BITS (0x0 << 13)
|
||||
#define DMA_CR_MSIZE_16BITS (0x1 << 13)
|
||||
#define DMA_CR_MSIZE_32BITS (0x2 << 13)
|
||||
|
||||
#define DMA_CR_PSIZE_8BITS (0x0 << 11)
|
||||
#define DMA_CR_PSIZE_16BITS (0x1 << 11)
|
||||
#define DMA_CR_PSIZE_32BITS (0x2 << 11)
|
||||
|
||||
#define DMA_CR_MINC (0x1 << 10)
|
||||
#define DMA_CR_PINC (0x1 << 9)
|
||||
#define DMA_CR_CIRC (0x1 << 8)
|
||||
#define DMA_CR_DIR_P2M (0x0 << 6)
|
||||
#define DMA_CR_DIR_M2P (0x1 << 6)
|
||||
#define DMA_CR_DIR_M2M (0x2 << 6)
|
||||
|
||||
#define DMA_CR_PFCTRL (0x1 << 5)
|
||||
#define DMA_CR_TCIE (0x1 << 4)
|
||||
#define DMA_CR_HTIE (0x1 << 3)
|
||||
#define DMA_CR_TEIE (0x1 << 2)
|
||||
#define DMA_CR_DMEIE (0x1 << 1)
|
||||
#define DMA_CR_EN (0x1)
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
/** Encapsulates state related to a DMA channel interrupt. */
|
||||
typedef struct dma_handler_config {
|
||||
void (*handler)(void); /**< User-specified channel interrupt
|
||||
handler */
|
||||
nvic_irq_num irq_line; /**< Channel's NVIC interrupt number */
|
||||
} dma_handler_config;
|
||||
|
||||
/** DMA device type */
|
||||
typedef struct dma_dev {
|
||||
dma_reg_map *regs; /**< Register map */
|
||||
rcc_clk_id clk_id; /**< Clock ID */
|
||||
dma_handler_config handlers[]; /**<
|
||||
* @brief IRQ handlers and NVIC numbers.
|
||||
*
|
||||
* @see dma_attach_interrupt()
|
||||
* @see dma_detach_interrupt()
|
||||
*/
|
||||
} dma_dev;
|
||||
|
||||
extern dma_dev *DMA1;
|
||||
extern dma_dev *DMA2;
|
||||
|
||||
/*
|
||||
* Convenience functions
|
||||
*/
|
||||
|
||||
void dma_init(dma_dev *dev);
|
||||
|
||||
/** Flags for DMA transfer configuration. */
|
||||
typedef enum dma_mode_flags {
|
||||
DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */
|
||||
DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */
|
||||
DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */
|
||||
DMA_CIRC_MODE = 1 << 5, /**< Circular mode */
|
||||
DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */
|
||||
DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */
|
||||
DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */
|
||||
DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */
|
||||
} dma_mode_flags;
|
||||
|
||||
/** Source and destination transfer sizes. */
|
||||
typedef enum dma_xfer_size {
|
||||
DMA_SIZE_8BITS = 0, /**< 8-bit transfers */
|
||||
DMA_SIZE_16BITS = 1, /**< 16-bit transfers */
|
||||
DMA_SIZE_32BITS = 2 /**< 32-bit transfers */
|
||||
} dma_xfer_size;
|
||||
|
||||
/** DMA channel */
|
||||
typedef enum dma_stream {
|
||||
DMA_STREAM0 = 0, /**< Stream 0 */
|
||||
DMA_STREAM1 = 1, /**< Stream 1 */
|
||||
DMA_STREAM2 = 2, /**< Stream 2 */
|
||||
DMA_STREAM3 = 3, /**< Stream 3 */
|
||||
DMA_STREAM4 = 4, /**< Stream 4 */
|
||||
DMA_STREAM5 = 5, /**< Stream 5 */
|
||||
DMA_STREAM6 = 6, /**< Stream 6 */
|
||||
DMA_STREAM7 = 7, /**< Stream 7 */
|
||||
} dma_stream;
|
||||
|
||||
static inline void dma_setup_transfer(dma_dev *dev,
|
||||
dma_stream stream,
|
||||
__io void *peripheral_address,
|
||||
__io void *memory_address0,
|
||||
__io void *memory_address1,
|
||||
uint32 flags,
|
||||
uint32 fifo_flags) {
|
||||
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN; // disable
|
||||
dev->regs->STREAM[stream].PAR = (uint32)peripheral_address;
|
||||
dev->regs->STREAM[stream].M0AR = (uint32)memory_address0;
|
||||
dev->regs->STREAM[stream].M1AR = (uint32)memory_address1;
|
||||
dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits
|
||||
dev->regs->STREAM[stream].CR = flags & 0x0feffffe; // mask out reserved and enable
|
||||
}
|
||||
|
||||
static inline void dma_set_num_transfers(dma_dev *dev,
|
||||
dma_stream stream,
|
||||
uint16 num_transfers) {
|
||||
dev->regs->STREAM[stream].NDTR = num_transfers;
|
||||
}
|
||||
|
||||
void dma_attach_interrupt(dma_dev *dev,
|
||||
dma_stream stream,
|
||||
void (*handler)(void));
|
||||
|
||||
void dma_detach_interrupt(dma_dev *dev, dma_stream stream);
|
||||
|
||||
static inline void dma_enable(dma_dev *dev, dma_stream stream) {
|
||||
dev->regs->STREAM[stream].CR |= DMA_CR_EN;
|
||||
}
|
||||
|
||||
static inline void dma_disable(dma_dev *dev, dma_stream stream) {
|
||||
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a DMA stream is enabled
|
||||
* @param dev DMA device
|
||||
* @param stream Stream whose enabled bit to check.
|
||||
*/
|
||||
static inline uint8 dma_is_stream_enabled(dma_dev *dev, dma_stream stream) {
|
||||
return (uint8)(dev->regs->STREAM[stream].CR & DMA_CR_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the ISR status bits for a DMA stream.
|
||||
*
|
||||
* The bits are returned right-aligned, in the following order:
|
||||
* transfer error flag, half-transfer flag, transfer complete flag,
|
||||
* global interrupt flag.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param stream Stream whose ISR bits to return.
|
||||
*/
|
||||
uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream);
|
||||
|
||||
/**
|
||||
* @brief Clear the ISR status bits for a given DMA stream.
|
||||
*
|
||||
* @param dev DMA device
|
||||
* @param stream Stream whose ISR bits to clear.
|
||||
*/
|
||||
void dma_clear_isr_bits(dma_dev *dev, dma_stream stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
/* *****************************************************************************
|
||||
* 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.
|
||||
* ****************************************************************************/
|
||||
|
||||
# On an exception, push a fake stack thread mode stack frame and redirect
|
||||
# thread execution to a thread mode error handler
|
||||
|
||||
# From RM008:
|
||||
# The SP is decremented by eight words by the completion of the stack push.
|
||||
# Figure 5-1 shows the contents of the stack after an exception pre-empts the
|
||||
# current program flow.
|
||||
#
|
||||
# Old SP--> <previous>
|
||||
# xPSR
|
||||
# PC
|
||||
# LR
|
||||
# r12
|
||||
# r3
|
||||
# r2
|
||||
# r1
|
||||
# SP--> r0
|
||||
|
||||
.text
|
||||
.globl __exc_hardfault
|
||||
.globl __exc_nmi
|
||||
.globl __exc_hardfault
|
||||
.globl __exc_memmanage
|
||||
.globl __exc_busfault
|
||||
.globl __exc_usagefault
|
||||
|
||||
.code 16
|
||||
.thumb_func
|
||||
__exc_nmi:
|
||||
mov r0, #1
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_hardfault:
|
||||
mov r0, #2
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_memmanage:
|
||||
mov r0, #3
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_busfault:
|
||||
mov r0, #4
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_usagefault:
|
||||
mov r0, #5
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__default_exc:
|
||||
b __default_exc
|
||||
|
||||
|
||||
ldr r2, NVIC_CCR @ Enable returning to thread mode even if there are
|
||||
mov r1 ,#1 @ pending exceptions. See flag NONEBASETHRDENA.
|
||||
str r1, [r2]
|
||||
cpsid i @ Disable global interrupts
|
||||
ldr r2, SYSTICK_CSR @ Disable systick handler
|
||||
mov r1, #0
|
||||
str r1, [r2]
|
||||
ldr r1, CPSR_MASK @ Set default CPSR
|
||||
push {r1}
|
||||
ldr r1, TARGET_PC @ Set target pc
|
||||
push {r1}
|
||||
sub sp, sp, #24 @ Don't care
|
||||
ldr r1, EXC_RETURN @ Return to thread mode
|
||||
mov lr, r1
|
||||
bx lr @ Exception exit
|
||||
|
||||
.align 4
|
||||
CPSR_MASK: .word 0x61000000
|
||||
EXC_RETURN: .word 0xFFFFFFF9
|
||||
TARGET_PC: .word __error
|
||||
NVIC_CCR: .word 0xE000ED14 @ NVIC configuration control register
|
||||
SYSTICK_CSR: .word 0xE000E010 @ Systick control register
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file exti.c
|
||||
* @brief External interrupt control routines
|
||||
*/
|
||||
|
||||
#include "exti.h"
|
||||
#include "libmaple.h"
|
||||
#include "nvic.h"
|
||||
#include "bitband.h"
|
||||
|
||||
static inline void dispatch_single_exti(uint32 exti_num);
|
||||
static inline void dispatch_extis(uint32 start, uint32 stop);
|
||||
|
||||
/*
|
||||
* Internal state
|
||||
*/
|
||||
|
||||
typedef struct exti_channel {
|
||||
void (*handler)(void);
|
||||
uint32 irq_line;
|
||||
} exti_channel;
|
||||
|
||||
static exti_channel exti_channels[] = {
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI0 }, // EXTI0
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI1 }, // EXTI1
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI2 }, // EXTI2
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI3 }, // EXTI3
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI4 }, // EXTI4
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI5
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI6
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI7
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI8
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI9
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI10
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI11
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI12
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI13
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI14
|
||||
{ .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI15
|
||||
};
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Register a handler to run upon external interrupt.
|
||||
*
|
||||
* This function assumes that the interrupt request corresponding to
|
||||
* the given external interrupt is masked.
|
||||
*
|
||||
* @param num External interrupt line number.
|
||||
* @param port Port to use as source input for external interrupt.
|
||||
* @param handler Function handler to execute when interrupt is triggered.
|
||||
* @param mode Type of transition to trigger on, one of:
|
||||
* EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING.
|
||||
* @see afio_exti_num
|
||||
* @see afio_exti_port
|
||||
* @see voidFuncPtr
|
||||
* @see exti_trigger_mode
|
||||
*/
|
||||
void exti_attach_interrupt(afio_exti_num num,
|
||||
afio_exti_port port,
|
||||
voidFuncPtr handler,
|
||||
exti_trigger_mode mode) {
|
||||
ASSERT(handler);
|
||||
|
||||
/* Register the handler */
|
||||
exti_channels[num].handler = handler;
|
||||
|
||||
/* Set trigger mode */
|
||||
switch (mode) {
|
||||
case EXTI_RISING:
|
||||
bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1);
|
||||
break;
|
||||
case EXTI_FALLING:
|
||||
bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1);
|
||||
break;
|
||||
case EXTI_RISING_FALLING:
|
||||
bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1);
|
||||
bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Map num to port */
|
||||
afio_exti_select(num, port);
|
||||
|
||||
/* Unmask external interrupt request */
|
||||
bb_peri_set_bit(&EXTI_BASE->IMR, num, 1);
|
||||
|
||||
/* Enable the interrupt line */
|
||||
nvic_irq_enable(exti_channels[num].irq_line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an external interrupt handler
|
||||
* @param num Number of the external interrupt line to disable.
|
||||
* @see afio_exti_num
|
||||
*/
|
||||
void exti_detach_interrupt(afio_exti_num num) {
|
||||
/* First, mask the interrupt request */
|
||||
bb_peri_set_bit(&EXTI_BASE->IMR, num, 0);
|
||||
|
||||
/* Then, clear the trigger selection registers */
|
||||
bb_peri_set_bit(&EXTI_BASE->FTSR, num, 0);
|
||||
bb_peri_set_bit(&EXTI_BASE->RTSR, num, 0);
|
||||
|
||||
/* Finally, unregister the user's handler */
|
||||
exti_channels[num].handler = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handlers
|
||||
*/
|
||||
|
||||
void __irq_exti0(void) {
|
||||
dispatch_single_exti(AFIO_EXTI_0);
|
||||
}
|
||||
|
||||
void __irq_exti1(void) {
|
||||
dispatch_single_exti(AFIO_EXTI_1);
|
||||
}
|
||||
|
||||
void __irq_exti2(void) {
|
||||
dispatch_single_exti(AFIO_EXTI_2);
|
||||
}
|
||||
|
||||
void __irq_exti3(void) {
|
||||
dispatch_single_exti(AFIO_EXTI_3);
|
||||
}
|
||||
|
||||
void __irq_exti4(void) {
|
||||
dispatch_single_exti(AFIO_EXTI_4);
|
||||
}
|
||||
|
||||
void __irq_exti9_5(void) {
|
||||
dispatch_extis(5, 9);
|
||||
}
|
||||
|
||||
void __irq_exti15_10(void) {
|
||||
dispatch_extis(10, 15);
|
||||
}
|
||||
|
||||
/*
|
||||
* Auxiliary functions
|
||||
*/
|
||||
|
||||
/* Clear the pending bits for EXTIs whose bits are set in exti_msk.
|
||||
*
|
||||
* If a pending bit is cleared as the last instruction in an ISR, it
|
||||
* won't actually be cleared in time and the ISR will fire again. To
|
||||
* compensate, this function NOPs for 2 cycles after clearing the
|
||||
* pending bits to ensure it takes effect. */
|
||||
static inline void clear_pending_msk(uint32 exti_msk) {
|
||||
EXTI_BASE->PR = exti_msk;
|
||||
asm volatile("nop");
|
||||
asm volatile("nop");
|
||||
}
|
||||
|
||||
/* This dispatch routine is for non-multiplexed EXTI lines only; i.e.,
|
||||
* it doesn't check EXTI_PR. */
|
||||
static inline void dispatch_single_exti(uint32 exti) {
|
||||
voidFuncPtr handler = exti_channels[exti].handler;
|
||||
|
||||
if (!handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
handler();
|
||||
clear_pending_msk(BIT(exti));
|
||||
}
|
||||
|
||||
/* Dispatch routine for EXTIs which share an IRQ. */
|
||||
static inline void dispatch_extis(uint32 start, uint32 stop) {
|
||||
uint32 pr = EXTI_BASE->PR;
|
||||
uint32 handled_msk = 0;
|
||||
uint32 exti;
|
||||
|
||||
/* Dispatch user handlers for pending EXTIs. */
|
||||
for (exti = start; exti <= stop; exti++) {
|
||||
uint32 eb = BIT(exti);
|
||||
if (pr & eb) {
|
||||
voidFuncPtr handler = exti_channels[exti].handler;
|
||||
if (handler) {
|
||||
handler();
|
||||
handled_msk |= eb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the pending bits for handled EXTIs. */
|
||||
clear_pending_msk(handled_msk);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file exti.h
|
||||
* @brief External interrupt control prototypes and defines
|
||||
*/
|
||||
|
||||
/* See notes/exti.txt for more info */
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#ifndef _EXTI_H_
|
||||
#define _EXTI_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** EXTI register map type */
|
||||
typedef struct exti_reg_map {
|
||||
__io uint32 IMR; /**< Interrupt mask register */
|
||||
__io uint32 EMR; /**< Event mask register */
|
||||
__io uint32 RTSR; /**< Rising trigger selection register */
|
||||
__io uint32 FTSR; /**< Falling trigger selection register */
|
||||
__io uint32 SWIER; /**< Software interrupt event register */
|
||||
__io uint32 PR; /**< Pending register */
|
||||
} exti_reg_map;
|
||||
|
||||
/** EXTI register map base pointer */
|
||||
#ifdef STM32F2
|
||||
#define EXTI_BASE ((struct exti_reg_map*)0x40013C00)
|
||||
#else
|
||||
#define EXTI_BASE ((struct exti_reg_map*)0x40010400)
|
||||
#endif
|
||||
|
||||
/** External interrupt trigger mode */
|
||||
typedef enum exti_trigger_mode {
|
||||
EXTI_RISING, /**< Trigger on the rising edge */
|
||||
EXTI_FALLING, /**< Trigger on the falling edge */
|
||||
EXTI_RISING_FALLING /**< Trigger on both the rising and falling edges */
|
||||
} exti_trigger_mode;
|
||||
|
||||
void exti_attach_interrupt(afio_exti_num num,
|
||||
afio_exti_port port,
|
||||
voidFuncPtr handler,
|
||||
exti_trigger_mode mode);
|
||||
void exti_detach_interrupt(afio_exti_num num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file flash.c
|
||||
* @brief Flash management functions
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "flash.h"
|
||||
#include "bitband.h"
|
||||
|
||||
/**
|
||||
* @brief Turn on the hardware prefetcher.
|
||||
*/
|
||||
void flash_enable_prefetch(void) {
|
||||
*bb_perip(&FLASH_BASE->ACR, FLASH_ACR_PRFTBE_BIT) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set flash wait states
|
||||
*
|
||||
* See ST PM0042, section 3.1 for restrictions on the acceptable value
|
||||
* of wait_states for a given SYSCLK configuration.
|
||||
*
|
||||
* @param wait_states number of wait states (one of
|
||||
* FLASH_WAIT_STATE_0, FLASH_WAIT_STATE_1,
|
||||
* FLASH_WAIT_STATE_2).
|
||||
*/
|
||||
void flash_set_latency(uint32 wait_states) {
|
||||
uint32 val = FLASH_BASE->ACR;
|
||||
|
||||
val &= ~FLASH_ACR_LATENCY;
|
||||
val |= wait_states;
|
||||
|
||||
FLASH_BASE->ACR = val;
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file flash.h
|
||||
* @brief STM32 Medium and high density Flash register map and setup
|
||||
* routines
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
#ifndef _FLASH_H_
|
||||
#define _FLASH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** Flash register map type */
|
||||
typedef struct flash_reg_map {
|
||||
__io uint32 ACR; /**< Access control register */
|
||||
__io uint32 KEYR; /**< Key register */
|
||||
__io uint32 OPTKEYR; /**< OPTKEY register */
|
||||
__io uint32 SR; /**< Status register */
|
||||
__io uint32 CR; /**< Control register */
|
||||
__io uint32 AR; /**< Address register */
|
||||
__io uint32 OBR; /**< Option byte register */
|
||||
__io uint32 WRPR; /**< Write protection register */
|
||||
} flash_reg_map;
|
||||
|
||||
/** Flash register map base pointer */
|
||||
#define FLASH_BASE ((struct flash_reg_map*)0x40022000)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Access control register */
|
||||
|
||||
#define FLASH_ACR_PRFTBS_BIT 5
|
||||
#define FLASH_ACR_PRFTBE_BIT 4
|
||||
#define FLASH_ACR_HLFCYA_BIT 3
|
||||
|
||||
#define FLASH_ACR_PRFTBS BIT(FLASH_ACR_PRFTBS_BIT)
|
||||
#define FLASH_ACR_PRFTBE BIT(FLASH_ACR_PRFTBE_BIT)
|
||||
#define FLASH_ACR_HLFCYA BIT(FLASH_ACR_HLFCYA_BIT)
|
||||
#define FLASH_ACR_LATENCY 0x7
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define FLASH_SR_EOP_BIT 5
|
||||
#define FLASH_SR_WRPRTERR_BIT 4
|
||||
#define FLASH_SR_PGERR_BIT 2
|
||||
#define FLASH_SR_BSY_BIT 0
|
||||
|
||||
#define FLASH_SR_EOP BIT(FLASH_SR_EOP_BIT)
|
||||
#define FLASH_SR_WRPRTERR BIT(FLASH_SR_WRPRTERR_BIT)
|
||||
#define FLASH_SR_PGERR BIT(FLASH_SR_PGERR_BIT)
|
||||
#define FLASH_SR_BSY BIT(FLASH_SR_BSY_BIT)
|
||||
|
||||
/* Control register */
|
||||
|
||||
#define FLASH_CR_EOPIE_BIT 12
|
||||
#define FLASH_CR_ERRIE_BIT 10
|
||||
#define FLASH_CR_OPTWRE_BIT 9
|
||||
#define FLASH_CR_LOCK_BIT 7
|
||||
#define FLASH_CR_STRT_BIT 6
|
||||
#define FLASH_CR_OPTER_BIT 5
|
||||
#define FLASH_CR_OPTPG_BIT 4
|
||||
#define FLASH_CR_MER_BIT 2
|
||||
#define FLASH_CR_PER_BIT 1
|
||||
#define FLASH_CR_PG_BIT 0
|
||||
|
||||
#define FLASH_CR_EOPIE BIT(FLASH_CR_EOPIE_BIT)
|
||||
#define FLASH_CR_ERRIE BIT(FLASH_CR_ERRIE_BIT)
|
||||
#define FLASH_CR_OPTWRE BIT(FLASH_CR_OPTWRE_BIT)
|
||||
#define FLASH_CR_LOCK BIT(FLASH_CR_LOCK_BIT)
|
||||
#define FLASH_CR_STRT BIT(FLASH_CR_STRT_BIT)
|
||||
#define FLASH_CR_OPTER BIT(FLASH_CR_OPTER_BIT)
|
||||
#define FLASH_CR_OPTPG BIT(FLASH_CR_OPTPG_BIT)
|
||||
#define FLASH_CR_MER BIT(FLASH_CR_MER_BIT)
|
||||
#define FLASH_CR_PER BIT(FLASH_CR_PER_BIT)
|
||||
#define FLASH_CR_PG BIT(FLASH_CR_PG_BIT)
|
||||
|
||||
/* Option byte register */
|
||||
|
||||
#define FLASH_OBR_nRST_STDBY_BIT 4
|
||||
#define FLASH_OBR_nRST_STOP_BIT 3
|
||||
#define FLASH_OBR_WDG_SW_BIT 2
|
||||
#define FLASH_OBR_RDPRT_BIT 1
|
||||
#define FLASH_OBR_OPTERR_BIT 0
|
||||
|
||||
#define FLASH_OBR_DATA1 (0xFF << 18)
|
||||
#define FLASH_OBR_DATA0 (0xFF << 10)
|
||||
#define FLASH_OBR_USER 0x3FF
|
||||
#define FLASH_OBR_nRST_STDBY BIT(FLASH_OBR_nRST_STDBY_BIT)
|
||||
#define FLASH_OBR_nRST_STOP BIT(FLASH_OBR_nRST_STOP_BIT)
|
||||
#define FLASH_OBR_WDG_SW BIT(FLASH_OBR_WDG_SW_BIT)
|
||||
#define FLASH_OBR_RDPRT BIT(FLASH_OBR_RDPRT_BIT)
|
||||
#define FLASH_OBR_OPTERR BIT(FLASH_OBR_OPTERR_BIT)
|
||||
|
||||
/*
|
||||
* Setup routines
|
||||
*/
|
||||
|
||||
#define FLASH_WAIT_STATE_0 0x0
|
||||
#define FLASH_WAIT_STATE_1 0x1
|
||||
#define FLASH_WAIT_STATE_2 0x2
|
||||
|
||||
void flash_enable_prefetch(void);
|
||||
void flash_set_latency(uint32 wait_states);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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 fsmc.c
|
||||
* @brief Flexible static memory controller support.
|
||||
*/
|
||||
|
||||
#include "fsmc.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
|
||||
/**
|
||||
* Configure FSMC GPIOs for use with SRAM.
|
||||
*/
|
||||
void fsmc_sram_init_gpios(void) {
|
||||
/* Data lines... */
|
||||
gpio_set_mode(GPIOD, 0, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 1, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 8, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 9, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 10, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 14, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 15, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 7, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 8, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 9, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 10, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 11, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 12, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 13, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 14, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 15, GPIO_AF_OUTPUT_PP);
|
||||
|
||||
/* Address lines... */
|
||||
gpio_set_mode(GPIOD, 11, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 12, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 13, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 0, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 1, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 2, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 3, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 4, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 5, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 12, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 13, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 14, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 15, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 0, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 1, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 2, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 3, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 4, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 5, GPIO_AF_OUTPUT_PP);
|
||||
|
||||
/* And control lines... */
|
||||
gpio_set_mode(GPIOD, 4, GPIO_AF_OUTPUT_PP); // NOE
|
||||
gpio_set_mode(GPIOD, 5, GPIO_AF_OUTPUT_PP); // NWE
|
||||
|
||||
gpio_set_mode(GPIOD, 7, GPIO_AF_OUTPUT_PP); // NE1
|
||||
gpio_set_mode(GPIOG, 9, GPIO_AF_OUTPUT_PP); // NE2
|
||||
gpio_set_mode(GPIOG, 10, GPIO_AF_OUTPUT_PP); // NE3
|
||||
gpio_set_mode(GPIOG, 12, GPIO_AF_OUTPUT_PP); // NE4
|
||||
|
||||
gpio_set_mode(GPIOE, 0, GPIO_AF_OUTPUT_PP); // NBL0
|
||||
gpio_set_mode(GPIOE, 1, GPIO_AF_OUTPUT_PP); // NBL1
|
||||
}
|
||||
|
||||
#endif /* STM32_HIGH_DENSITY */
|
|
@ -0,0 +1,320 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
* 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 fsmc.h
|
||||
* @brief Flexible static memory controller support.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See ../notes/fsmc.txt for more info
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
/**
|
||||
* @file fsmc.h
|
||||
*/
|
||||
|
||||
#ifndef _FSMC_H_
|
||||
#define _FSMC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
|
||||
/*
|
||||
* Register maps and devices
|
||||
*/
|
||||
|
||||
/** FSMC register map type */
|
||||
typedef struct fsmc_reg_map {
|
||||
__io uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */
|
||||
__io uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */
|
||||
__io uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */
|
||||
__io uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */
|
||||
__io uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */
|
||||
__io uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */
|
||||
__io uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */
|
||||
__io uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */
|
||||
const uint8 RESERVED1[64]; /**< Reserved */
|
||||
__io uint32 PCR2; /**< PC Card/NAND Flash control register 2 */
|
||||
__io uint32 SR2; /**< FIFO status and interrupt register 2 */
|
||||
__io uint32 PMEM2; /**< Common memory space timing register 2 */
|
||||
__io uint32 PATT2; /**< Attribute memory space timing register 2 */
|
||||
const uint8 RESERVED2[4]; /**< Reserved */
|
||||
__io uint32 ECCR2; /**< ECC result register 2 */
|
||||
const uint8 RESERVED3[2];
|
||||
__io uint32 PCR3; /**< PC Card/NAND Flash control register 3 */
|
||||
__io uint32 SR3; /**< FIFO status and interrupt register 3 */
|
||||
__io uint32 PMEM3; /**< Common memory space timing register 3 */
|
||||
__io uint32 PATT3; /**< Attribute memory space timing register 3 */
|
||||
const uint32 RESERVED4; /**< Reserved */
|
||||
__io uint32 ECCR3; /**< ECC result register 3 */
|
||||
const uint8 RESERVED5[8]; /**< Reserved */
|
||||
__io uint32 PCR4; /**< PC Card/NAND Flash control register 4 */
|
||||
__io uint32 SR4; /**< FIFO status and interrupt register 4 */
|
||||
__io uint32 PMEM4; /**< Common memory space timing register 4 */
|
||||
__io uint32 PATT4; /**< Attribute memory space timing register 4 */
|
||||
__io uint32 PIO4; /**< I/O space timing register 4 */
|
||||
const uint8 RESERVED6[80]; /**< Reserved */
|
||||
__io uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */
|
||||
const uint32 RESERVED7; /**< Reserved */
|
||||
__io uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */
|
||||
const uint32 RESERVED8; /**< Reserved */
|
||||
__io uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */
|
||||
const uint32 RESERVED9; /**< Reserved */
|
||||
__io uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */
|
||||
} __attribute__((packed)) fsmc_reg_map;
|
||||
|
||||
#define __FSMCB 0xA0000000
|
||||
|
||||
/** FSMC register map base pointer */
|
||||
#define FSMC_BASE ((struct fsmc_reg_map*)__FSMCB)
|
||||
|
||||
/** FSMC NOR/PSRAM register map type */
|
||||
typedef struct fsmc_nor_psram_reg_map {
|
||||
__io uint32 BCR; /**< Chip-select control register */
|
||||
__io uint32 BTR; /**< Chip-select timing register */
|
||||
const uint8 RESERVED[252]; /**< Reserved */
|
||||
__io uint32 BWTR; /**< Write timing register */
|
||||
} fsmc_nor_psram_reg_map;
|
||||
|
||||
/** FSMC NOR/PSRAM base pointer 1 */
|
||||
#define FSMC_NOR_PSRAM1_BASE ((struct fsmc_nor_psram_reg_map*)__FSMCB)
|
||||
|
||||
/** FSMC NOR/PSRAM base pointer 2 */
|
||||
#define FSMC_NOR_PSRAM2_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x8))
|
||||
|
||||
/** FSMC NOR/PSRAM base pointer 3 */
|
||||
#define FSMC_NOR_PSRAM3_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x10))
|
||||
|
||||
/** FSMC NOR/PSRAM base pointer 4 */
|
||||
#define FSMC_NOR_PSRAM4_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x18))
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* NOR/PSRAM chip-select control registers */
|
||||
|
||||
#define FSMC_BCR_CBURSTRW_BIT 19
|
||||
#define FSMC_BCR_ASYNCWAIT_BIT 15
|
||||
#define FSMC_BCR_EXTMOD_BIT 14
|
||||
#define FSMC_BCR_WAITEN_BIT 13
|
||||
#define FSMC_BCR_WREN_BIT 12
|
||||
#define FSMC_BCR_WAITCFG_BIT 11
|
||||
#define FSMC_BCR_WRAPMOD_BIT 10
|
||||
#define FSMC_BCR_WAITPOL_BIT 9
|
||||
#define FSMC_BCR_BURSTEN_BIT 8
|
||||
#define FSMC_BCR_FACCEN_BIT 6
|
||||
#define FSMC_BCR_MUXEN_BIT 1
|
||||
#define FSMC_BCR_MBKEN_BIT 0
|
||||
|
||||
#define FSMC_BCR_CBURSTRW BIT(FSMC_BCR_CBURSTRW_BIT)
|
||||
#define FSMC_BCR_ASYNCWAIT BIT(FSMC_BCR_ASYNCWAIT_BIT)
|
||||
#define FSMC_BCR_EXTMOD BIT(FSMC_BCR_EXTMOD_BIT)
|
||||
#define FSMC_BCR_WAITEN BIT(FSMC_BCR_WAITEN_BIT)
|
||||
#define FSMC_BCR_WREN BIT(FSMC_BCR_WREN_BIT)
|
||||
#define FSMC_BCR_WAITCFG BIT(FSMC_BCR_WAITCFG_BIT)
|
||||
#define FSMC_BCR_WRAPMOD BIT(FSMC_BCR_WRAPMOD_BIT)
|
||||
#define FSMC_BCR_WAITPOL BIT(FSMC_BCR_WAITPOL_BIT)
|
||||
#define FSMC_BCR_BURSTEN BIT(FSMC_BCR_BURSTEN_BIT)
|
||||
#define FSMC_BCR_FACCEN BIT(FSMC_BCR_FACCEN_BIT)
|
||||
#define FSMC_BCR_MWID (0x3 << 4)
|
||||
#define FSMC_BCR_MWID_8BITS (0x0 << 4)
|
||||
#define FSMC_BCR_MWID_16BITS (0x1 << 4)
|
||||
#define FSMC_BCR_MTYP (0x3 << 2)
|
||||
#define FSMC_BCR_MTYP_SRAM (0x0 << 2)
|
||||
#define FSMC_BCR_MTYP_PSRAM (0x1 << 2)
|
||||
#define FSMC_BCR_MTYP_NOR_FLASH (0x2 << 2)
|
||||
#define FSMC_BCR_MUXEN BIT(FSMC_BCR_MUXEN_BIT)
|
||||
#define FSMC_BCR_MBKEN BIT(FSMC_BCR_MBKEN_BIT)
|
||||
|
||||
/* SRAM/NOR-Flash chip-select timing registers */
|
||||
|
||||
#define FSMC_BTR_ACCMOD (0x3 << 28)
|
||||
#define FSMC_BTR_ACCMOD_A (0x0 << 28)
|
||||
#define FSMC_BTR_ACCMOD_B (0x1 << 28)
|
||||
#define FSMC_BTR_ACCMOD_C (0x2 << 28)
|
||||
#define FSMC_BTR_ACCMOD_D (0x3 << 28)
|
||||
#define FSMC_BTR_DATLAT (0xF << 24)
|
||||
#define FSMC_BTR_CLKDIV (0xF << 20)
|
||||
#define FSMC_BTR_BUSTURN (0xF << 16)
|
||||
#define FSMC_BTR_DATAST (0xFF << 8)
|
||||
#define FSMC_BTR_ADDHLD (0xF << 4)
|
||||
#define FSMC_BTR_ADDSET 0xF
|
||||
|
||||
/* SRAM/NOR-Flash write timing registers */
|
||||
|
||||
#define FSMC_BWTR_ACCMOD (0x3 << 28)
|
||||
#define FSMC_BWTR_ACCMOD_A (0x0 << 28)
|
||||
#define FSMC_BWTR_ACCMOD_B (0x1 << 28)
|
||||
#define FSMC_BWTR_ACCMOD_C (0x2 << 28)
|
||||
#define FSMC_BWTR_ACCMOD_D (0x3 << 28)
|
||||
#define FSMC_BWTR_DATLAT (0xF << 24)
|
||||
#define FSMC_BWTR_CLKDIV (0xF << 20)
|
||||
#define FSMC_BWTR_DATAST (0xFF << 8)
|
||||
#define FSMC_BWTR_ADDHLD (0xF << 4)
|
||||
#define FSMC_BWTR_ADDSET 0xF
|
||||
|
||||
/* NAND Flash/PC Card controller registers */
|
||||
|
||||
#define FSMC_PCR_ECCEN_BIT 6
|
||||
#define FSMC_PCR_PTYP_BIT 3
|
||||
#define FSMC_PCR_PBKEN_BIT 2
|
||||
#define FSMC_PCR_PWAITEN_BIT 1
|
||||
|
||||
#define FSMC_PCR_ECCPS (0x7 << 17)
|
||||
#define FSMC_PCR_ECCPS_256B (0x0 << 17)
|
||||
#define FSMC_PCR_ECCPS_512B (0x1 << 17)
|
||||
#define FSMC_PCR_ECCPS_1024B (0x2 << 17)
|
||||
#define FSMC_PCR_ECCPS_2048B (0x3 << 17)
|
||||
#define FSMC_PCR_ECCPS_4096B (0x4 << 17)
|
||||
#define FSMC_PCR_ECCPS_8192B (0x5 << 17)
|
||||
#define FSMC_PCR_TAR (0xF << 13)
|
||||
#define FSMC_PCR_TCLR (0xF << 9)
|
||||
#define FSMC_PCR_ECCEN BIT(FSMC_PCR_ECCEN_BIT)
|
||||
#define FSMC_PCR_PWID (0x3 << 4)
|
||||
#define FSMC_PCR_PWID_8BITS (0x0 << 4)
|
||||
#define FSMC_PCR_PWID_16BITS (0x1 << 4)
|
||||
#define FSMC_PCR_PTYP BIT(FSMC_PCR_PTYP_BIT)
|
||||
#define FSMC_PCR_PTYP_PC_CF_PCMCIA (0x0 << FSMC_PCR_PTYP_BIT)
|
||||
#define FSMC_PCR_PTYP_NAND (0x1 << FSMC_PCR_PTYP_BIT)
|
||||
#define FSMC_PCR_PBKEN BIT(FSMC_PCR_PBKEN_BIT)
|
||||
#define FSMC_PCR_PWAITEN BIT(FSMC_PCR_PWAITEN_BIT)
|
||||
|
||||
/* FIFO status and interrupt registers */
|
||||
|
||||
#define FSMC_SR_FEMPT_BIT 6
|
||||
#define FSMC_SR_IFEN_BIT 5
|
||||
#define FSMC_SR_ILEN_BIT 4
|
||||
#define FSMC_SR_IREN_BIT 3
|
||||
#define FSMC_SR_IFS_BIT 2
|
||||
#define FSMC_SR_ILS_BIT 1
|
||||
#define FSMC_SR_IRS_BIT 0
|
||||
|
||||
#define FSMC_SR_FEMPT BIT(FSMC_SR_FEMPT_BIT)
|
||||
#define FSMC_SR_IFEN BIT(FSMC_SR_IFEN_BIT)
|
||||
#define FSMC_SR_ILEN BIT(FSMC_SR_ILEN_BIT)
|
||||
#define FSMC_SR_IREN BIT(FSMC_SR_IREN_BIT)
|
||||
#define FSMC_SR_IFS BIT(FSMC_SR_IFS_BIT)
|
||||
#define FSMC_SR_ILS BIT(FSMC_SR_ILS_BIT)
|
||||
#define FSMC_SR_IRS BIT(FSMC_SR_IRS_BIT)
|
||||
|
||||
/* Common memory space timing registers */
|
||||
|
||||
#define FSMC_PMEM_MEMHIZ (0xFF << 24)
|
||||
#define FSMC_PMEM_MEMHOLD (0xFF << 16)
|
||||
#define FSMC_PMEM_MEMWAIT (0xFF << 8)
|
||||
#define FSMC_PMEM_MEMSET 0xFF
|
||||
|
||||
/* Attribute memory space timing registers */
|
||||
|
||||
#define FSMC_PATT_ATTHIZ (0xFF << 24)
|
||||
#define FSMC_PATT_ATTHOLD (0xFF << 16)
|
||||
#define FSMC_PATT_ATTWAIT (0xFF << 8)
|
||||
#define FSMC_PATT_ATTSET 0xFF
|
||||
|
||||
/* I/O space timing register 4 */
|
||||
|
||||
#define FSMC_PIO_IOHIZ (0xFF << 24)
|
||||
#define FSMC_PIO_IOHOLD (0xFF << 16)
|
||||
#define FSMC_PIO_IOWAIT (0xFF << 8)
|
||||
#define FSMC_PIO_IOSET 0xFF
|
||||
|
||||
/*
|
||||
* Memory bank boundary addresses
|
||||
*/
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 1 (split into 4
|
||||
* regions, each supporting 1 NOR Flash, SRAM, or PSRAM chip) */
|
||||
#define FSMC_BANK1 ((void*)0x60000000)
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 1, region 1 (for NOR/PSRAM) */
|
||||
#define FSMC_NOR_PSRAM_REGION1 FSMC_BANK1
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 1, region 2 (for NOR/PSRAM) */
|
||||
#define FSMC_NOR_PSRAM_REGION2 ((void*)0x64000000)
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 1, region 3 (for NOR/PSRAM) */
|
||||
#define FSMC_NOR_PSRAM_REGION3 ((void*)0x68000000)
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 1, region 4 (for NOR/PSRAM) */
|
||||
#define FSMC_NOR_PSRAM_REGION4 ((void*)0x6C000000)
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 2 (for NAND Flash) */
|
||||
#define FSMC_BANK2 ((void*)0x70000000)
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 3 (for NAND Flash) */
|
||||
#define FSMC_BANK3 ((void*)0x80000000)
|
||||
|
||||
/** Pointer to base address of FSMC memory bank 4 (for PC card devices */
|
||||
#define FSMC_BANK4 ((void*)0x90000000)
|
||||
|
||||
/*
|
||||
* SRAM/NOR Flash routines
|
||||
*/
|
||||
|
||||
void fsmc_sram_init_gpios(void);
|
||||
|
||||
/**
|
||||
* Set the DATAST bits in the given NOR/PSRAM register map's
|
||||
* chip-select timing register (FSMC_BTR).
|
||||
*
|
||||
* @param regs NOR Flash/PSRAM register map whose chip-select timing
|
||||
* register to set.
|
||||
* @param datast Value to use for DATAST bits.
|
||||
*/
|
||||
static inline void fsmc_nor_psram_set_datast(fsmc_nor_psram_reg_map *regs,
|
||||
uint8 datast) {
|
||||
regs->BTR &= ~FSMC_BTR_DATAST;
|
||||
regs->BTR |= datast << 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ADDHLD bits in the given NOR/PSRAM register map's chip
|
||||
* select timing register (FSMC_BTRx).
|
||||
*
|
||||
* @param regs NOR Flash/PSRAM register map whose chip-select timing
|
||||
* register to set.
|
||||
* @param addset Value to use for ADDSET bits.
|
||||
*/
|
||||
static inline void fsmc_nor_psram_set_addset(fsmc_nor_psram_reg_map *regs,
|
||||
uint8 addset) {
|
||||
regs->BTR &= ~FSMC_BTR_ADDSET;
|
||||
regs->BTR |= addset & 0xF;
|
||||
}
|
||||
|
||||
#endif /* STM32_HIGH_DENSITY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file gpio.c
|
||||
* @brief GPIO initialization routine
|
||||
*/
|
||||
|
||||
// #ifdef STM32F2
|
||||
// #include "gpioF2.c"
|
||||
// #else
|
||||
// #include "gpioF1.c"
|
||||
// #endif
|
|
@ -0,0 +1,38 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file gpio.h
|
||||
*
|
||||
* @brief General purpose I/O (GPIO) and Alternate Function I/O
|
||||
* (AFIO) prototypes, defines, and inlined access functions.
|
||||
*/
|
||||
|
||||
#ifdef STM32F2
|
||||
#include "gpioF2.h"
|
||||
#else
|
||||
#include "gpioF1.h"
|
||||
#endif
|
|
@ -0,0 +1,200 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef STM32F1
|
||||
|
||||
/**
|
||||
* @file gpio.c
|
||||
* @brief GPIO initialization routine
|
||||
*/
|
||||
|
||||
#include "gpio.h"
|
||||
#include "rcc.h"
|
||||
|
||||
/*
|
||||
* GPIO devices
|
||||
*/
|
||||
|
||||
gpio_dev gpioa = {
|
||||
.regs = GPIOA_BASE,
|
||||
.clk_id = RCC_GPIOA,
|
||||
.exti_port = AFIO_EXTI_PA,
|
||||
};
|
||||
/** GPIO port A device. */
|
||||
gpio_dev* const GPIOA = &gpioa;
|
||||
|
||||
gpio_dev gpiob = {
|
||||
.regs = GPIOB_BASE,
|
||||
.clk_id = RCC_GPIOB,
|
||||
.exti_port = AFIO_EXTI_PB,
|
||||
};
|
||||
/** GPIO port B device. */
|
||||
gpio_dev* const GPIOB = &gpiob;
|
||||
|
||||
gpio_dev gpioc = {
|
||||
.regs = GPIOC_BASE,
|
||||
.clk_id = RCC_GPIOC,
|
||||
.exti_port = AFIO_EXTI_PC,
|
||||
};
|
||||
/** GPIO port C device. */
|
||||
gpio_dev* const GPIOC = &gpioc;
|
||||
|
||||
gpio_dev gpiod = {
|
||||
.regs = GPIOD_BASE,
|
||||
.clk_id = RCC_GPIOD,
|
||||
.exti_port = AFIO_EXTI_PD,
|
||||
};
|
||||
/** GPIO port D device. */
|
||||
gpio_dev* const GPIOD = &gpiod;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
gpio_dev gpioe = {
|
||||
.regs = GPIOE_BASE,
|
||||
.clk_id = RCC_GPIOE,
|
||||
.exti_port = AFIO_EXTI_PE,
|
||||
};
|
||||
/** GPIO port E device. */
|
||||
gpio_dev* const GPIOE = &gpioe;
|
||||
|
||||
gpio_dev gpiof = {
|
||||
.regs = GPIOF_BASE,
|
||||
.clk_id = RCC_GPIOF,
|
||||
.exti_port = AFIO_EXTI_PF,
|
||||
};
|
||||
/** GPIO port F device. */
|
||||
gpio_dev* const GPIOF = &gpiof;
|
||||
|
||||
gpio_dev gpiog = {
|
||||
.regs = GPIOG_BASE,
|
||||
.clk_id = RCC_GPIOG,
|
||||
.exti_port = AFIO_EXTI_PG,
|
||||
};
|
||||
/** GPIO port G device. */
|
||||
gpio_dev* const GPIOG = &gpiog;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize a GPIO device.
|
||||
*
|
||||
* Enables the clock for and resets the given device.
|
||||
*
|
||||
* @param dev GPIO device to initialize.
|
||||
*/
|
||||
void gpio_init(gpio_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and reset all available GPIO devices.
|
||||
*/
|
||||
void gpio_init_all(void) {
|
||||
gpio_init(GPIOA);
|
||||
gpio_init(GPIOB);
|
||||
gpio_init(GPIOC);
|
||||
gpio_init(GPIOD);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
gpio_init(GPIOE);
|
||||
gpio_init(GPIOF);
|
||||
gpio_init(GPIOG);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode of a GPIO pin.
|
||||
*
|
||||
* @param dev GPIO device.
|
||||
* @param pin Pin on the device whose mode to set, 0--15.
|
||||
* @param mode General purpose or alternate function mode to set the pin to.
|
||||
* @see gpio_pin_mode
|
||||
*/
|
||||
void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) {
|
||||
gpio_reg_map *regs = dev->regs;
|
||||
__io uint32 *cr = ®s->CRL + (pin >> 3);
|
||||
uint32 shift = (pin & 0x7) * 4;
|
||||
uint32 tmp = *cr;
|
||||
|
||||
tmp &= ~(0xF << shift);
|
||||
tmp |= (mode == GPIO_INPUT_PU ? GPIO_INPUT_PD : mode) << shift;
|
||||
*cr = tmp;
|
||||
|
||||
if (mode == GPIO_INPUT_PD) {
|
||||
regs->ODR &= ~BIT(pin);
|
||||
} else if (mode == GPIO_INPUT_PU) {
|
||||
regs->ODR |= BIT(pin);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AFIO
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the AFIO clock, and reset the AFIO registers.
|
||||
*/
|
||||
void afio_init(void) {
|
||||
rcc_clk_enable(RCC_AFIO);
|
||||
rcc_reset_dev(RCC_AFIO);
|
||||
}
|
||||
|
||||
#define AFIO_EXTI_SEL_MASK 0xF
|
||||
|
||||
/**
|
||||
* @brief Select a source input for an external interrupt.
|
||||
*
|
||||
* @param exti External interrupt.
|
||||
* @param gpio_port Port which contains pin to use as source input.
|
||||
* @see afio_exti_num
|
||||
* @see afio_exti_port
|
||||
*/
|
||||
void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) {
|
||||
__io uint32 *exti_cr = &AFIO_BASE->EXTICR1 + exti / 4;
|
||||
uint32 shift = 4 * (exti % 4);
|
||||
uint32 cr = *exti_cr;
|
||||
|
||||
cr &= ~(AFIO_EXTI_SEL_MASK << shift);
|
||||
cr |= gpio_port << shift;
|
||||
*exti_cr = cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform an alternate function remap.
|
||||
* @param remapping Remapping to perform.
|
||||
*/
|
||||
void afio_remap(afio_remap_peripheral remapping) {
|
||||
if (remapping & AFIO_REMAP_USE_MAPR2) {
|
||||
remapping &= ~AFIO_REMAP_USE_MAPR2;
|
||||
AFIO_BASE->MAPR2 |= remapping;
|
||||
} else {
|
||||
AFIO_BASE->MAPR |= remapping;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,530 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file gpio.h
|
||||
*
|
||||
* @brief General purpose I/O (GPIO) and Alternate Function I/O
|
||||
* (AFIO) prototypes, defines, and inlined access functions.
|
||||
*/
|
||||
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "rcc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO register maps and devices
|
||||
*/
|
||||
|
||||
/** GPIO register map type */
|
||||
typedef struct gpio_reg_map {
|
||||
__io uint32 CRL; /**< Port configuration register low */
|
||||
__io uint32 CRH; /**< Port configuration register high */
|
||||
__io uint32 IDR; /**< Port input data register */
|
||||
__io uint32 ODR; /**< Port output data register */
|
||||
__io uint32 BSRR; /**< Port bit set/reset register */
|
||||
__io uint32 BRR; /**< Port bit reset register */
|
||||
__io uint32 LCKR; /**< Port configuration lock register */
|
||||
} gpio_reg_map;
|
||||
|
||||
/**
|
||||
* @brief External interrupt line port selector.
|
||||
*
|
||||
* Used to determine which GPIO port to map an external interrupt line
|
||||
* onto. */
|
||||
/* (See AFIO sections, below) */
|
||||
typedef enum afio_exti_port {
|
||||
AFIO_EXTI_PA, /**< Use port A (PAx) pin. */
|
||||
AFIO_EXTI_PB, /**< Use port B (PBx) pin. */
|
||||
AFIO_EXTI_PC, /**< Use port C (PCx) pin. */
|
||||
AFIO_EXTI_PD, /**< Use port D (PDx) pin. */
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
AFIO_EXTI_PE, /**< Use port E (PEx) pin. */
|
||||
AFIO_EXTI_PF, /**< Use port F (PFx) pin. */
|
||||
AFIO_EXTI_PG, /**< Use port G (PGx) pin. */
|
||||
#endif
|
||||
} afio_exti_port;
|
||||
|
||||
/** GPIO device type */
|
||||
typedef struct gpio_dev {
|
||||
gpio_reg_map *regs; /**< Register map */
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
afio_exti_port exti_port; /**< AFIO external interrupt port value */
|
||||
} gpio_dev;
|
||||
|
||||
extern gpio_dev gpioa;
|
||||
extern gpio_dev* const GPIOA;
|
||||
extern gpio_dev gpiob;
|
||||
extern gpio_dev* const GPIOB;
|
||||
extern gpio_dev gpioc;
|
||||
extern gpio_dev* const GPIOC;
|
||||
extern gpio_dev gpiod;
|
||||
extern gpio_dev* const GPIOD;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
extern gpio_dev gpioe;
|
||||
extern gpio_dev* const GPIOE;
|
||||
extern gpio_dev gpiof;
|
||||
extern gpio_dev* const GPIOF;
|
||||
extern gpio_dev gpiog;
|
||||
extern gpio_dev* const GPIOG;
|
||||
#endif
|
||||
|
||||
/** GPIO port A register map base pointer */
|
||||
#define GPIOA_BASE ((struct gpio_reg_map*)0x40010800)
|
||||
/** GPIO port B register map base pointer */
|
||||
#define GPIOB_BASE ((struct gpio_reg_map*)0x40010C00)
|
||||
/** GPIO port C register map base pointer */
|
||||
#define GPIOC_BASE ((struct gpio_reg_map*)0x40011000)
|
||||
/** GPIO port D register map base pointer */
|
||||
#define GPIOD_BASE ((struct gpio_reg_map*)0x40011400)
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
/** GPIO port E register map base pointer */
|
||||
#define GPIOE_BASE ((struct gpio_reg_map*)0x40011800)
|
||||
/** GPIO port F register map base pointer */
|
||||
#define GPIOF_BASE ((struct gpio_reg_map*)0x40011C00)
|
||||
/** GPIO port G register map base pointer */
|
||||
#define GPIOG_BASE ((struct gpio_reg_map*)0x40012000)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO register bit definitions
|
||||
*/
|
||||
|
||||
/* Control registers, low and high */
|
||||
|
||||
#define GPIO_CR_CNF (0x3 << 2)
|
||||
#define GPIO_CR_CNF_INPUT_ANALOG (0x0 << 2)
|
||||
#define GPIO_CR_CNF_INPUT_FLOATING (0x1 << 2)
|
||||
#define GPIO_CR_CNF_INPUT_PU_PD (0x2 << 2)
|
||||
#define GPIO_CR_CNF_OUTPUT_PP (0x0 << 2)
|
||||
#define GPIO_CR_CNF_OUTPUT_OD (0x1 << 2)
|
||||
#define GPIO_CR_CNF_AF_OUTPUT_PP (0x2 << 2)
|
||||
#define GPIO_CR_CNF_AF_OUTPUT_OD (0x3 << 2)
|
||||
#define GPIO_CR_MODE 0x3
|
||||
#define GPIO_CR_MODE_INPUT 0x0
|
||||
#define GPIO_CR_MODE_OUTPUT_10MHZ 0x1
|
||||
#define GPIO_CR_MODE_OUTPUT_2MHZ 0x2
|
||||
#define GPIO_CR_MODE_OUTPUT_50MHZ 0x3
|
||||
|
||||
/**
|
||||
* @brief GPIO Pin modes.
|
||||
*
|
||||
* These only allow for 50MHZ max output speeds; if you want slower,
|
||||
* use direct register access.
|
||||
*/
|
||||
typedef enum gpio_pin_mode {
|
||||
GPIO_OUTPUT_PP = (GPIO_CR_CNF_OUTPUT_PP |
|
||||
GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output push-pull. */
|
||||
GPIO_OUTPUT_OD = (GPIO_CR_CNF_OUTPUT_OD |
|
||||
GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output open-drain. */
|
||||
GPIO_AF_OUTPUT_PP = (GPIO_CR_CNF_AF_OUTPUT_PP |
|
||||
GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function
|
||||
output push-pull. */
|
||||
GPIO_AF_OUTPUT_OD = (GPIO_CR_CNF_AF_OUTPUT_OD |
|
||||
GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function
|
||||
output open drain. */
|
||||
GPIO_INPUT_ANALOG = (GPIO_CR_CNF_INPUT_ANALOG |
|
||||
GPIO_CR_MODE_INPUT), /**< Analog input. */
|
||||
GPIO_INPUT_FLOATING = (GPIO_CR_CNF_INPUT_FLOATING |
|
||||
GPIO_CR_MODE_INPUT), /**< Input floating. */
|
||||
GPIO_INPUT_PD = (GPIO_CR_CNF_INPUT_PU_PD |
|
||||
GPIO_CR_MODE_INPUT), /**< Input pull-down. */
|
||||
GPIO_AF_INPUT_PD = (GPIO_INPUT_PD), /**< Input pull-down. */
|
||||
GPIO_INPUT_PU /**< Input pull-up. */
|
||||
|
||||
|
||||
/* GPIO_INPUT_PU treated as a special case, for ODR twiddling */
|
||||
} gpio_pin_mode;
|
||||
|
||||
/*
|
||||
* GPIO Convenience routines
|
||||
*/
|
||||
|
||||
void gpio_init(gpio_dev *dev);
|
||||
void gpio_init_all(void);
|
||||
void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode);
|
||||
|
||||
/**
|
||||
* @brief Get a GPIO port's corresponding afio_exti_port.
|
||||
* @param dev GPIO device whose afio_exti_port to return.
|
||||
*/
|
||||
static inline afio_exti_port gpio_exti_port(gpio_dev *dev) {
|
||||
return dev->exti_port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or reset a GPIO pin.
|
||||
*
|
||||
* Pin must have previously been configured to output mode.
|
||||
*
|
||||
* @param dev GPIO device whose pin to set.
|
||||
* @param pin Pin on to set or reset
|
||||
* @param val If true, set the pin. If false, reset the pin.
|
||||
*/
|
||||
static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) {
|
||||
if (val) {
|
||||
dev->regs->BSRR = BIT(pin);
|
||||
} else {
|
||||
dev->regs->BRR = BIT(pin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not a GPIO pin is set.
|
||||
*
|
||||
* Pin must have previously been configured to input mode.
|
||||
*
|
||||
* @param dev GPIO device whose pin to test.
|
||||
* @param pin Pin on dev to test.
|
||||
* @return True if the pin is set, false otherwise.
|
||||
*/
|
||||
static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) {
|
||||
return dev->regs->IDR & BIT(pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle a pin configured as output push-pull.
|
||||
* @param dev GPIO device.
|
||||
* @param pin Pin on dev to toggle.
|
||||
*/
|
||||
static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) {
|
||||
dev->regs->ODR = dev->regs->ODR ^ BIT(pin);
|
||||
}
|
||||
|
||||
/*
|
||||
* AFIO register map
|
||||
*/
|
||||
|
||||
/** AFIO register map */
|
||||
typedef struct afio_reg_map {
|
||||
__io uint32 EVCR; /**< Event control register. */
|
||||
__io uint32 MAPR; /**< AF remap and debug I/O configuration
|
||||
register. */
|
||||
__io uint32 EXTICR1; /**< External interrupt configuration
|
||||
register 1. */
|
||||
__io uint32 EXTICR2; /**< External interrupt configuration
|
||||
register 2. */
|
||||
__io uint32 EXTICR3; /**< External interrupt configuration
|
||||
register 3. */
|
||||
__io uint32 EXTICR4; /**< External interrupt configuration
|
||||
register 4. */
|
||||
__io uint32 MAPR2; /**< AF remap and debug I/O configuration
|
||||
register 2. */
|
||||
} afio_reg_map;
|
||||
|
||||
/** AFIO register map base pointer. */
|
||||
#define AFIO_BASE ((struct afio_reg_map *)0x40010000)
|
||||
|
||||
/*
|
||||
* AFIO register bit definitions
|
||||
*/
|
||||
|
||||
/* Event control register */
|
||||
|
||||
#define AFIO_EVCR_EVOE (0x1 << 7)
|
||||
#define AFIO_EVCR_PORT_PA (0x0 << 4)
|
||||
#define AFIO_EVCR_PORT_PB (0x1 << 4)
|
||||
#define AFIO_EVCR_PORT_PC (0x2 << 4)
|
||||
#define AFIO_EVCR_PORT_PD (0x3 << 4)
|
||||
#define AFIO_EVCR_PORT_PE (0x4 << 4)
|
||||
#define AFIO_EVCR_PIN_0 0x0
|
||||
#define AFIO_EVCR_PIN_1 0x1
|
||||
#define AFIO_EVCR_PIN_2 0x2
|
||||
#define AFIO_EVCR_PIN_3 0x3
|
||||
#define AFIO_EVCR_PIN_4 0x4
|
||||
#define AFIO_EVCR_PIN_5 0x5
|
||||
#define AFIO_EVCR_PIN_6 0x6
|
||||
#define AFIO_EVCR_PIN_7 0x7
|
||||
#define AFIO_EVCR_PIN_8 0x8
|
||||
#define AFIO_EVCR_PIN_9 0x9
|
||||
#define AFIO_EVCR_PIN_10 0xA
|
||||
#define AFIO_EVCR_PIN_11 0xB
|
||||
#define AFIO_EVCR_PIN_12 0xC
|
||||
#define AFIO_EVCR_PIN_13 0xD
|
||||
#define AFIO_EVCR_PIN_14 0xE
|
||||
#define AFIO_EVCR_PIN_15 0xF
|
||||
|
||||
/* AF remap and debug I/O configuration register */
|
||||
|
||||
#define AFIO_MAPR_SWJ_CFG (0x7 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_FULL_SWJ (0x0 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24)
|
||||
#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20)
|
||||
#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19)
|
||||
#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18)
|
||||
#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17)
|
||||
#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16)
|
||||
#define AFIO_MAPR_PD01_REMAP BIT(15)
|
||||
#define AFIO_MAPR_CAN_REMAP (0x3 << 13)
|
||||
#define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13)
|
||||
#define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13)
|
||||
#define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13)
|
||||
#define AFIO_MAPR_TIM4_REMAP BIT(12)
|
||||
#define AFIO_MAPR_TIM3_REMAP (0x3 << 10)
|
||||
#define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10)
|
||||
#define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10)
|
||||
#define AFIO_MAPR_TIM3_REMAP_FULL (0x3 << 10)
|
||||
#define AFIO_MAPR_TIM2_REMAP (0x3 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_NONE (0x0 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3 (0x1 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11 (0x2 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_FULL (0x3 << 8)
|
||||
#define AFIO_MAPR_TIM1_REMAP (0x3 << 6)
|
||||
#define AFIO_MAPR_TIM1_REMAP_NONE (0x0 << 6)
|
||||
#define AFIO_MAPR_TIM1_REMAP_PARTIAL (0x1 << 6)
|
||||
#define AFIO_MAPR_TIM1_REMAP_FULL (0x3 << 6)
|
||||
#define AFIO_MAPR_USART3_REMAP (0x3 << 4)
|
||||
#define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4)
|
||||
#define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4)
|
||||
#define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4)
|
||||
#define AFIO_MAPR_USART2_REMAP BIT(3)
|
||||
#define AFIO_MAPR_USART1_REMAP BIT(2)
|
||||
#define AFIO_MAPR_I2C1_REMAP BIT(1)
|
||||
#define AFIO_MAPR_SPI1_REMAP BIT(0)
|
||||
|
||||
/* External interrupt configuration register 1 */
|
||||
|
||||
#define AFIO_EXTICR1_EXTI3 (0xF << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PA (0x0 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PB (0x1 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PC (0x2 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PD (0x3 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PE (0x4 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PF (0x5 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PG (0x6 << 12)
|
||||
#define AFIO_EXTICR1_EXTI2 (0xF << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PA (0x0 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PB (0x1 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PC (0x2 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PD (0x3 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PE (0x4 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PF (0x5 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PG (0x6 << 8)
|
||||
#define AFIO_EXTICR1_EXTI1 (0xF << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PA (0x0 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PB (0x1 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PC (0x2 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PD (0x3 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PE (0x4 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PF (0x5 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PG (0x6 << 4)
|
||||
#define AFIO_EXTICR1_EXTI0 0xF
|
||||
#define AFIO_EXTICR1_EXTI0_PA 0x0
|
||||
#define AFIO_EXTICR1_EXTI0_PB 0x1
|
||||
#define AFIO_EXTICR1_EXTI0_PC 0x2
|
||||
#define AFIO_EXTICR1_EXTI0_PD 0x3
|
||||
#define AFIO_EXTICR1_EXTI0_PE 0x4
|
||||
#define AFIO_EXTICR1_EXTI0_PF 0x5
|
||||
#define AFIO_EXTICR1_EXTI0_PG 0x6
|
||||
|
||||
/* External interrupt configuration register 2 */
|
||||
|
||||
#define AFIO_EXTICR2_EXTI7 (0xF << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PA (0x0 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PB (0x1 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PC (0x2 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PD (0x3 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PE (0x4 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PF (0x5 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PG (0x6 << 12)
|
||||
#define AFIO_EXTICR2_EXTI6 (0xF << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PA (0x0 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PB (0x1 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PC (0x2 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PD (0x3 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PE (0x4 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PF (0x5 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PG (0x6 << 8)
|
||||
#define AFIO_EXTICR2_EXTI5 (0xF << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PA (0x0 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PB (0x1 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PC (0x2 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PD (0x3 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PE (0x4 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PF (0x5 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PG (0x6 << 4)
|
||||
#define AFIO_EXTICR2_EXTI4 0xF
|
||||
#define AFIO_EXTICR2_EXTI4_PA 0x0
|
||||
#define AFIO_EXTICR2_EXTI4_PB 0x1
|
||||
#define AFIO_EXTICR2_EXTI4_PC 0x2
|
||||
#define AFIO_EXTICR2_EXTI4_PD 0x3
|
||||
#define AFIO_EXTICR2_EXTI4_PE 0x4
|
||||
#define AFIO_EXTICR2_EXTI4_PF 0x5
|
||||
#define AFIO_EXTICR2_EXTI4_PG 0x6
|
||||
|
||||
/* AF remap and debug I/O configuration register 2 */
|
||||
|
||||
#define AFIO_MAPR2_FSMC_NADV BIT(10)
|
||||
#define AFIO_MAPR2_TIM14_REMAP BIT(9)
|
||||
#define AFIO_MAPR2_TIM13_REMAP BIT(8)
|
||||
#define AFIO_MAPR2_TIM11_REMAP BIT(7)
|
||||
#define AFIO_MAPR2_TIM10_REMAP BIT(6)
|
||||
#define AFIO_MAPR2_TIM9_REMAP BIT(5)
|
||||
|
||||
/*
|
||||
* AFIO convenience routines
|
||||
*/
|
||||
|
||||
void afio_init(void);
|
||||
|
||||
/**
|
||||
* External interrupt line numbers.
|
||||
*/
|
||||
typedef enum afio_exti_num {
|
||||
AFIO_EXTI_0, /**< External interrupt line 0. */
|
||||
AFIO_EXTI_1, /**< External interrupt line 1. */
|
||||
AFIO_EXTI_2, /**< External interrupt line 2. */
|
||||
AFIO_EXTI_3, /**< External interrupt line 3. */
|
||||
AFIO_EXTI_4, /**< External interrupt line 4. */
|
||||
AFIO_EXTI_5, /**< External interrupt line 5. */
|
||||
AFIO_EXTI_6, /**< External interrupt line 6. */
|
||||
AFIO_EXTI_7, /**< External interrupt line 7. */
|
||||
AFIO_EXTI_8, /**< External interrupt line 8. */
|
||||
AFIO_EXTI_9, /**< External interrupt line 9. */
|
||||
AFIO_EXTI_10, /**< External interrupt line 10. */
|
||||
AFIO_EXTI_11, /**< External interrupt line 11. */
|
||||
AFIO_EXTI_12, /**< External interrupt line 12. */
|
||||
AFIO_EXTI_13, /**< External interrupt line 13. */
|
||||
AFIO_EXTI_14, /**< External interrupt line 14. */
|
||||
AFIO_EXTI_15, /**< External interrupt line 15. */
|
||||
} afio_exti_num;
|
||||
|
||||
void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port);
|
||||
|
||||
/* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and
|
||||
* not used in either MAPR or MAPR2 */
|
||||
#define AFIO_REMAP_USE_MAPR2 (1 << 31)
|
||||
|
||||
/**
|
||||
* @brief Available peripheral remaps.
|
||||
* @see afio_remap()
|
||||
*/
|
||||
typedef enum afio_remap_peripheral {
|
||||
AFIO_REMAP_ADC2_ETRGREG = AFIO_MAPR_ADC2_ETRGREG_REMAP, /**<
|
||||
ADC 2 external trigger regular conversion remapping */
|
||||
AFIO_REMAP_ADC2_ETRGINJ = AFIO_MAPR_ADC2_ETRGINJ_REMAP, /**<
|
||||
ADC 2 external trigger injected conversion remapping */
|
||||
AFIO_REMAP_ADC1_ETRGREG = AFIO_MAPR_ADC1_ETRGREG_REMAP, /**<
|
||||
ADC 1 external trigger regular conversion remapping */
|
||||
AFIO_REMAP_ADC1_ETRGINJ = AFIO_MAPR_ADC1_ETRGINJ_REMAP, /**<
|
||||
ADC 1 external trigger injected conversion remapping */
|
||||
AFIO_REMAP_TIM5CH4_I = AFIO_MAPR_TIM5CH4_IREMAP, /**<
|
||||
Timer 5 channel 4 internal remapping */
|
||||
AFIO_REMAP_PD01 = AFIO_MAPR_PD01_REMAP, /**<
|
||||
Port D0/Port D1 mapping on OSC_IN/OSC_OUT */
|
||||
AFIO_REMAP_CAN_1 = AFIO_MAPR_CAN_REMAP_PB8_PB9, /**<
|
||||
CAN alternate function remapping 1 (RX on PB8, TX on PB9) */
|
||||
AFIO_REMAP_CAN_2 = AFIO_MAPR_CAN_REMAP_PD0_PD1, /**<
|
||||
CAN alternate function remapping 2 (RX on PD0, TX on PD1) */
|
||||
AFIO_REMAP_TIM4 = AFIO_MAPR_TIM4_REMAP, /**<
|
||||
Timer 4 remapping */
|
||||
AFIO_REMAP_TIM3_PARTIAL = AFIO_MAPR_TIM3_REMAP_PARTIAL, /**<
|
||||
Timer 3 partial remapping */
|
||||
AFIO_REMAP_TIM3_FULL = AFIO_MAPR_TIM3_REMAP_FULL, /**<
|
||||
Timer 3 full remapping */
|
||||
AFIO_REMAP_TIM2_PARTIAL_1 = AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3, /**<
|
||||
Timer 2 partial remapping 1 (CH1 and ETR on PA15, CH2 on PB3, CH3
|
||||
on PA2, CH4 on PA3) */
|
||||
AFIO_REMAP_TIM2_PARTIAL_2 = AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11, /**<
|
||||
Timer 2 partial remapping 2 (CH1 and ETR on PA0, CH2 on PA1, CH3
|
||||
on PB10, CH4 on PB11) */
|
||||
AFIO_REMAP_TIM2_FULL = AFIO_MAPR_TIM2_REMAP_FULL, /**<
|
||||
Timer 2 full remapping */
|
||||
AFIO_REMAP_USART2 = AFIO_MAPR_USART2_REMAP, /**<
|
||||
USART 2 remapping */
|
||||
AFIO_REMAP_USART1 = AFIO_MAPR_USART1_REMAP, /**<
|
||||
USART 1 remapping */
|
||||
AFIO_REMAP_I2C1 = AFIO_MAPR_I2C1_REMAP, /**<
|
||||
I2C 1 remapping */
|
||||
AFIO_REMAP_SPI1 = AFIO_MAPR_SPI1_REMAP, /**<
|
||||
SPI 1 remapping */
|
||||
AFIO_REMAP_FSMC_NADV = (AFIO_MAPR2_FSMC_NADV |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
NADV signal not connected */
|
||||
AFIO_REMAP_TIM14 = (AFIO_MAPR2_TIM14_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 14 remapping */
|
||||
AFIO_REMAP_TIM13 = (AFIO_MAPR2_TIM13_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 13 remapping */
|
||||
AFIO_REMAP_TIM11 = (AFIO_MAPR2_TIM11_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 11 remapping */
|
||||
AFIO_REMAP_TIM10 = (AFIO_MAPR2_TIM10_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 10 remapping */
|
||||
AFIO_REMAP_TIM9 = (AFIO_MAPR2_TIM9_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2) /**<
|
||||
Timer 9 */
|
||||
} afio_remap_peripheral;
|
||||
|
||||
void afio_remap(afio_remap_peripheral p);
|
||||
|
||||
/**
|
||||
* @brief Debug port configuration
|
||||
*
|
||||
* Used to configure the behavior of JTAG and Serial Wire (SW) debug
|
||||
* ports and their associated GPIO pins.
|
||||
*
|
||||
* @see afio_cfg_debug_ports()
|
||||
*/
|
||||
typedef enum afio_debug_cfg {
|
||||
AFIO_DEBUG_FULL_SWJ = AFIO_MAPR_SWJ_CFG_FULL_SWJ, /**<
|
||||
Full Serial Wire and JTAG debug */
|
||||
AFIO_DEBUG_FULL_SWJ_NO_NJRST = AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST, /**<
|
||||
Full Serial Wire and JTAG, but no NJTRST. */
|
||||
AFIO_DEBUG_SW_ONLY = AFIO_MAPR_SWJ_CFG_NO_JTAG_SW, /**<
|
||||
Serial Wire debug only (JTAG-DP disabled,
|
||||
SW-DP enabled) */
|
||||
AFIO_DEBUG_NONE = AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW /**<
|
||||
No debug; all JTAG and SW pins are free
|
||||
for use as GPIOs. */
|
||||
} afio_debug_cfg;
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the JTAG and SW debug ports.
|
||||
* @param config Desired debug port configuration
|
||||
* @see afio_debug_cfg
|
||||
*/
|
||||
static inline void afio_cfg_debug_ports(afio_debug_cfg config) {
|
||||
__io uint32 *mapr = &AFIO_BASE->MAPR;
|
||||
*mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef STM32F2
|
||||
|
||||
/**
|
||||
* @file gpio.c
|
||||
* @brief GPIO initialization routine
|
||||
*/
|
||||
|
||||
#include "gpio.h"
|
||||
#include "rcc.h"
|
||||
|
||||
/*
|
||||
* GPIO devices
|
||||
*/
|
||||
|
||||
gpio_dev gpioa = {
|
||||
.regs = GPIOA_BASE,
|
||||
.clk_id = RCC_GPIOA,
|
||||
.exti_port = AFIO_EXTI_PA,
|
||||
};
|
||||
/** GPIO port A device. */
|
||||
gpio_dev* const GPIOA = &gpioa;
|
||||
|
||||
gpio_dev gpiob = {
|
||||
.regs = GPIOB_BASE,
|
||||
.clk_id = RCC_GPIOB,
|
||||
.exti_port = AFIO_EXTI_PB,
|
||||
};
|
||||
/** GPIO port B device. */
|
||||
gpio_dev* const GPIOB = &gpiob;
|
||||
|
||||
gpio_dev gpioc = {
|
||||
.regs = GPIOC_BASE,
|
||||
.clk_id = RCC_GPIOC,
|
||||
.exti_port = AFIO_EXTI_PC,
|
||||
};
|
||||
/** GPIO port C device. */
|
||||
gpio_dev* const GPIOC = &gpioc;
|
||||
|
||||
gpio_dev gpiod = {
|
||||
.regs = GPIOD_BASE,
|
||||
.clk_id = RCC_GPIOD,
|
||||
.exti_port = AFIO_EXTI_PD,
|
||||
};
|
||||
/** GPIO port D device. */
|
||||
gpio_dev* const GPIOD = &gpiod;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
gpio_dev gpioe = {
|
||||
.regs = GPIOE_BASE,
|
||||
.clk_id = RCC_GPIOE,
|
||||
.exti_port = AFIO_EXTI_PE,
|
||||
};
|
||||
/** GPIO port E device. */
|
||||
gpio_dev* const GPIOE = &gpioe;
|
||||
|
||||
gpio_dev gpiof = {
|
||||
.regs = GPIOF_BASE,
|
||||
.clk_id = RCC_GPIOF,
|
||||
.exti_port = AFIO_EXTI_PF,
|
||||
};
|
||||
/** GPIO port F device. */
|
||||
gpio_dev* const GPIOF = &gpiof;
|
||||
|
||||
gpio_dev gpiog = {
|
||||
.regs = GPIOG_BASE,
|
||||
.clk_id = RCC_GPIOG,
|
||||
.exti_port = AFIO_EXTI_PG,
|
||||
};
|
||||
/** GPIO port G device. */
|
||||
gpio_dev* const GPIOG = &gpiog;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize a GPIO device.
|
||||
*
|
||||
* Enables the clock for and resets the given device.
|
||||
*
|
||||
* @param dev GPIO device to initialize.
|
||||
*/
|
||||
void gpio_init(gpio_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and reset all available GPIO devices.
|
||||
*/
|
||||
void gpio_init_all(void) {
|
||||
gpio_init(GPIOA);
|
||||
gpio_init(GPIOB);
|
||||
gpio_init(GPIOC);
|
||||
gpio_init(GPIOD);
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
gpio_init(GPIOE);
|
||||
gpio_init(GPIOF);
|
||||
gpio_init(GPIOG);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode of a GPIO pin.
|
||||
*
|
||||
* @param dev GPIO device.
|
||||
* @param pin Pin on the device whose mode to set, 0--15.
|
||||
* @param mode General purpose or alternate function mode to set the pin to.
|
||||
* @see gpio_pin_mode
|
||||
*/
|
||||
void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) {
|
||||
gpio_reg_map *regs = dev->regs;
|
||||
|
||||
//regs->AFR[pin/8] = (regs->AFR[pin/8] & ~(15 << (4*(pin&7)))) | (((mode >> 8) & 15) << (4*(pin&7)));
|
||||
//gpio_set_af_mode(dev, pin, mode>>8);
|
||||
|
||||
regs->MODER = (regs->MODER & ~( 3 << (2*pin))) | (((mode >> 0) & 3) << (2*pin));
|
||||
regs->PUPDR = (regs->PUPDR & ~( 3 << (2*pin))) | (((mode >> 2) & 3) << (2*pin));
|
||||
regs->OSPEEDR = (regs->OSPEEDR & ~( 3 << (2*pin))) | (((mode >> 4) & 3) << (2*pin));
|
||||
regs->OTYPER = (regs->OTYPER & ~( 1 << (1*pin))) | (((mode >> 6) & 1) << (1*pin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alternate function mode of a GPIO pin.
|
||||
*
|
||||
* @param dev GPIO device.
|
||||
* @param pin Pin on the device whose mode to set, 0--15.
|
||||
* @param mode alternate function mode to set the pin to.
|
||||
* @see gpio_pin_mode
|
||||
*/
|
||||
void gpio_set_af_mode(gpio_dev *dev, uint8 pin, int mode) {
|
||||
gpio_reg_map *regs = dev->regs;
|
||||
|
||||
regs->AFR[pin/8] = (regs->AFR[pin/8] & ~(15 << (4*(pin&7)))) | (((mode >> 0) & 15) << (4*(pin&7)));
|
||||
}
|
||||
|
||||
/*
|
||||
* AFIO
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the AFIO clock, and reset the AFIO registers.
|
||||
*/
|
||||
void afio_init(void) {
|
||||
//rcc_clk_enable(RCC_AFIO);
|
||||
//rcc_reset_dev(RCC_AFIO);
|
||||
}
|
||||
|
||||
#define AFIO_EXTI_SEL_MASK 0xF
|
||||
|
||||
/**
|
||||
* @brief Select a source input for an external interrupt.
|
||||
*
|
||||
* @param exti External interrupt.
|
||||
* @param gpio_port Port which contains pin to use as source input.
|
||||
* @see afio_exti_num
|
||||
* @see afio_exti_port
|
||||
*/
|
||||
void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) {
|
||||
__io uint32 *exti_cr = &SYSCFG_BASE->EXTICR1 + exti / 4;
|
||||
uint32 shift = 4 * (exti % 4);
|
||||
uint32 cr = *exti_cr;
|
||||
|
||||
cr &= ~(AFIO_EXTI_SEL_MASK << shift);
|
||||
cr |= gpio_port << shift;
|
||||
*exti_cr = cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform an alternate function remap.
|
||||
* @param remapping Remapping to perform.
|
||||
*/
|
||||
#if 0
|
||||
void afio_remap(afio_remap_peripheral remapping) {
|
||||
if (remapping & AFIO_REMAP_USE_MAPR2) {
|
||||
remapping &= ~AFIO_REMAP_USE_MAPR2;
|
||||
AFIO_BASE->MAPR2 |= remapping;
|
||||
} else {
|
||||
AFIO_BASE->MAPR |= remapping;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,550 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file gpio.h
|
||||
*
|
||||
* @brief General purpose I/O (GPIO) and Alternate Function I/O
|
||||
* (AFIO) prototypes, defines, and inlined access functions.
|
||||
*/
|
||||
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "rcc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO register maps and devices
|
||||
*/
|
||||
|
||||
/** GPIO register map type */
|
||||
typedef struct gpio_reg_map {
|
||||
__io uint32 MODER; /*!< GPIO port mode register, Address offset: 0x00 */
|
||||
__io uint32 OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
|
||||
__io uint32 OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
|
||||
__io uint32 PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
|
||||
__io uint32 IDR; /*!< GPIO port input data register, Address offset: 0x10 */
|
||||
__io uint32 ODR; /*!< GPIO port output data register, Address offset: 0x14 */
|
||||
__io uint16 BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */
|
||||
__io uint16 BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */
|
||||
__io uint32 LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
|
||||
__io uint32 AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x24-0x28 */
|
||||
} gpio_reg_map;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief External interrupt line port selector.
|
||||
*
|
||||
* Used to determine which GPIO port to map an external interrupt line
|
||||
* onto. */
|
||||
/* (See AFIO sections, below) */
|
||||
typedef enum afio_exti_port {
|
||||
AFIO_EXTI_PA, /**< Use port A (PAx) pin. */
|
||||
AFIO_EXTI_PB, /**< Use port B (PBx) pin. */
|
||||
AFIO_EXTI_PC, /**< Use port C (PCx) pin. */
|
||||
AFIO_EXTI_PD, /**< Use port D (PDx) pin. */
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
AFIO_EXTI_PE, /**< Use port E (PEx) pin. */
|
||||
AFIO_EXTI_PF, /**< Use port F (PFx) pin. */
|
||||
AFIO_EXTI_PG, /**< Use port G (PGx) pin. */
|
||||
#endif
|
||||
} afio_exti_port;
|
||||
|
||||
/** GPIO device type */
|
||||
typedef struct gpio_dev {
|
||||
gpio_reg_map *regs; /**< Register map */
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
afio_exti_port exti_port; /**< AFIO external interrupt port value */
|
||||
} gpio_dev;
|
||||
|
||||
extern gpio_dev gpioa;
|
||||
extern gpio_dev* const GPIOA;
|
||||
extern gpio_dev gpiob;
|
||||
extern gpio_dev* const GPIOB;
|
||||
extern gpio_dev gpioc;
|
||||
extern gpio_dev* const GPIOC;
|
||||
extern gpio_dev gpiod;
|
||||
extern gpio_dev* const GPIOD;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
extern gpio_dev gpioe;
|
||||
extern gpio_dev* const GPIOE;
|
||||
extern gpio_dev gpiof;
|
||||
extern gpio_dev* const GPIOF;
|
||||
extern gpio_dev gpiog;
|
||||
extern gpio_dev* const GPIOG;
|
||||
#endif
|
||||
|
||||
/** GPIO port register map base pointer */
|
||||
#define GPIOA_BASE ((struct gpio_reg_map*)0x40020000)
|
||||
#define GPIOB_BASE ((struct gpio_reg_map*)0x40020400)
|
||||
#define GPIOC_BASE ((struct gpio_reg_map*)0x40020800)
|
||||
#define GPIOD_BASE ((struct gpio_reg_map*)0x40020C00)
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
#define GPIOE_BASE ((struct gpio_reg_map*)0x40021000)
|
||||
#define GPIOF_BASE ((struct gpio_reg_map*)0x40021400)
|
||||
#define GPIOG_BASE ((struct gpio_reg_map*)0x40021800)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO register bit definitions
|
||||
*/
|
||||
|
||||
#define GPIO_MODE_INPUT 0
|
||||
#define GPIO_MODE_OUTPUT 1
|
||||
#define GPIO_MODE_AF 2
|
||||
#define GPIO_MODE_ANALOG 3
|
||||
|
||||
#define GPIO_PUPD_INPUT_FLOATING (0 << 2)
|
||||
#define GPIO_PUPD_INPUT_PU (1 << 2)
|
||||
#define GPIO_PUPD_INPUT_PD (2 << 2)
|
||||
|
||||
#define GPIO_OSPEED_2MHZ (0 << 4)
|
||||
#define GPIO_OSPEED_25MHZ (1 << 4)
|
||||
#define GPIO_OSPEED_50MHZ (2 << 4)
|
||||
#define GPIO_OSPEED_100MHZ (3 << 4)
|
||||
|
||||
#define GPIO_OTYPE_PP (0 << 6)
|
||||
#define GPIO_OTYPE_OD (1 << 6)
|
||||
|
||||
/*
|
||||
MODER
|
||||
00: Input (reset state)
|
||||
01: General purpose output mode
|
||||
10: Alternate function mode
|
||||
11: Analog mode
|
||||
|
||||
OTYPER
|
||||
0: Output push-pull (reset state)
|
||||
1: Output open-drain
|
||||
|
||||
OSPEEDR
|
||||
00: 2 MHz Low speed
|
||||
01: 25 MHz Medium speed
|
||||
10: 50 MHz Fast speed
|
||||
11: 100 MHz High speed on 30 pF (80 MHz Output max speed on 15 pF)
|
||||
|
||||
PUPDR
|
||||
00: No pull-up, pull-down
|
||||
01: Pull-up
|
||||
10: Pull-down
|
||||
|
||||
AFRL 4 bit AF00-AF15
|
||||
AFRH 4 bit AF00-AF15
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief GPIO Pin modes.
|
||||
*
|
||||
* These only allow for 50MHZ max output speeds; if you want slower,
|
||||
* use direct register access.
|
||||
*/
|
||||
typedef enum gpio_pin_mode {
|
||||
GPIO_OUTPUT_PP = (GPIO_MODE_OUTPUT | GPIO_OTYPE_PP |
|
||||
GPIO_OSPEED_50MHZ), /**< Output push-pull. */
|
||||
GPIO_OUTPUT_OD = (GPIO_MODE_OUTPUT | GPIO_OTYPE_OD |
|
||||
GPIO_OSPEED_50MHZ), /**< Output open-drain. */
|
||||
GPIO_AF_OUTPUT_PP = (GPIO_MODE_AF | GPIO_OTYPE_PP |
|
||||
GPIO_OSPEED_50MHZ), /**< Alternate function
|
||||
output push-pull. */
|
||||
GPIO_AF_OUTPUT_OD = (GPIO_MODE_AF | GPIO_OTYPE_OD |
|
||||
GPIO_OSPEED_50MHZ), /**< Alternate function
|
||||
output open drain. */
|
||||
GPIO_INPUT_ANALOG = (GPIO_MODE_ANALOG), /**< Analog input. */
|
||||
GPIO_INPUT_FLOATING = (GPIO_MODE_INPUT |
|
||||
GPIO_PUPD_INPUT_FLOATING), /**< Input floating. */
|
||||
GPIO_INPUT_PD = (GPIO_MODE_INPUT |
|
||||
GPIO_PUPD_INPUT_PD), /**< Input pull-down. */
|
||||
GPIO_INPUT_PU = (GPIO_MODE_INPUT |
|
||||
GPIO_PUPD_INPUT_PU), /**< Input pull-up. */
|
||||
GPIO_AF_INPUT_PD = (GPIO_MODE_AF |
|
||||
GPIO_PUPD_INPUT_PD), /**< Input pull-down. */
|
||||
GPIO_BIGNUMBER = 0xfff
|
||||
} gpio_pin_mode;
|
||||
|
||||
/*
|
||||
* GPIO Convenience routines
|
||||
*/
|
||||
|
||||
void gpio_init(gpio_dev *dev);
|
||||
void gpio_init_all(void);
|
||||
void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode);
|
||||
void gpio_set_af_mode(gpio_dev *dev, uint8 pin, int mode);
|
||||
|
||||
/**
|
||||
* @brief Get a GPIO port's corresponding afio_exti_port.
|
||||
* @param dev GPIO device whose afio_exti_port to return.
|
||||
*/
|
||||
static inline afio_exti_port gpio_exti_port(gpio_dev *dev) {
|
||||
return dev->exti_port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or reset a GPIO pin.
|
||||
*
|
||||
* Pin must have previously been configured to output mode.
|
||||
*
|
||||
* @param dev GPIO device whose pin to set.
|
||||
* @param pin Pin on to set or reset
|
||||
* @param val If true, set the pin. If false, reset the pin.
|
||||
*/
|
||||
static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) {
|
||||
if (val) {
|
||||
dev->regs->BSRRL = BIT(pin);
|
||||
} else {
|
||||
dev->regs->BSRRH = BIT(pin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not a GPIO pin is set.
|
||||
*
|
||||
* Pin must have previously been configured to input mode.
|
||||
*
|
||||
* @param dev GPIO device whose pin to test.
|
||||
* @param pin Pin on dev to test.
|
||||
* @return True if the pin is set, false otherwise.
|
||||
*/
|
||||
static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) {
|
||||
return dev->regs->IDR & BIT(pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle a pin configured as output push-pull.
|
||||
* @param dev GPIO device.
|
||||
* @param pin Pin on dev to toggle.
|
||||
*/
|
||||
static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) {
|
||||
dev->regs->ODR = dev->regs->ODR ^ BIT(pin);
|
||||
}
|
||||
|
||||
/*
|
||||
* AFIO register map
|
||||
*/
|
||||
|
||||
/** AFIO register map */
|
||||
typedef struct syscfg_reg_map {
|
||||
__io uint32 MEMRM; /**< memory remap register */
|
||||
__io uint32 PMC; /**< peripheral mode configuration register */
|
||||
__io uint32 EXTICR1; /**< External interrupt configuration register 1. */
|
||||
__io uint32 EXTICR2; /**< External interrupt configuration register 2. */
|
||||
__io uint32 EXTICR3; /**< External interrupt configuration register 3. */
|
||||
__io uint32 EXTICR4; /**< External interrupt configuration register 4. */
|
||||
__io uint32 CMPCR; /**< Compensation cell control register */
|
||||
} syscfg_reg_map;
|
||||
|
||||
/** AFIO register map base pointer. */
|
||||
#define SYSCFG_BASE ((struct syscfg_reg_map *)0x40013800)
|
||||
|
||||
/*
|
||||
* AFIO register bit definitions
|
||||
*/
|
||||
|
||||
/* Event control register */
|
||||
|
||||
#define AFIO_EVCR_EVOE (0x1 << 7)
|
||||
#define AFIO_EVCR_PORT_PA (0x0 << 4)
|
||||
#define AFIO_EVCR_PORT_PB (0x1 << 4)
|
||||
#define AFIO_EVCR_PORT_PC (0x2 << 4)
|
||||
#define AFIO_EVCR_PORT_PD (0x3 << 4)
|
||||
#define AFIO_EVCR_PORT_PE (0x4 << 4)
|
||||
#define AFIO_EVCR_PIN_0 0x0
|
||||
#define AFIO_EVCR_PIN_1 0x1
|
||||
#define AFIO_EVCR_PIN_2 0x2
|
||||
#define AFIO_EVCR_PIN_3 0x3
|
||||
#define AFIO_EVCR_PIN_4 0x4
|
||||
#define AFIO_EVCR_PIN_5 0x5
|
||||
#define AFIO_EVCR_PIN_6 0x6
|
||||
#define AFIO_EVCR_PIN_7 0x7
|
||||
#define AFIO_EVCR_PIN_8 0x8
|
||||
#define AFIO_EVCR_PIN_9 0x9
|
||||
#define AFIO_EVCR_PIN_10 0xA
|
||||
#define AFIO_EVCR_PIN_11 0xB
|
||||
#define AFIO_EVCR_PIN_12 0xC
|
||||
#define AFIO_EVCR_PIN_13 0xD
|
||||
#define AFIO_EVCR_PIN_14 0xE
|
||||
#define AFIO_EVCR_PIN_15 0xF
|
||||
|
||||
/* AF remap and debug I/O configuration register */
|
||||
|
||||
#define AFIO_MAPR_SWJ_CFG (0x7 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_FULL_SWJ (0x0 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24)
|
||||
#define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24)
|
||||
#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20)
|
||||
#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19)
|
||||
#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18)
|
||||
#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17)
|
||||
#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16)
|
||||
#define AFIO_MAPR_PD01_REMAP BIT(15)
|
||||
#define AFIO_MAPR_CAN_REMAP (0x3 << 13)
|
||||
#define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13)
|
||||
#define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13)
|
||||
#define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13)
|
||||
#define AFIO_MAPR_TIM4_REMAP BIT(12)
|
||||
#define AFIO_MAPR_TIM3_REMAP (0x3 << 10)
|
||||
#define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10)
|
||||
#define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10)
|
||||
#define AFIO_MAPR_TIM3_REMAP_FULL (0x3 << 10)
|
||||
#define AFIO_MAPR_TIM2_REMAP (0x3 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_NONE (0x0 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3 (0x1 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11 (0x2 << 8)
|
||||
#define AFIO_MAPR_TIM2_REMAP_FULL (0x3 << 8)
|
||||
#define AFIO_MAPR_TIM1_REMAP (0x3 << 6)
|
||||
#define AFIO_MAPR_TIM1_REMAP_NONE (0x0 << 6)
|
||||
#define AFIO_MAPR_TIM1_REMAP_PARTIAL (0x1 << 6)
|
||||
#define AFIO_MAPR_TIM1_REMAP_FULL (0x3 << 6)
|
||||
#define AFIO_MAPR_USART3_REMAP (0x3 << 4)
|
||||
#define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4)
|
||||
#define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4)
|
||||
#define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4)
|
||||
#define AFIO_MAPR_USART2_REMAP BIT(3)
|
||||
#define AFIO_MAPR_USART1_REMAP BIT(2)
|
||||
#define AFIO_MAPR_I2C1_REMAP BIT(1)
|
||||
#define AFIO_MAPR_SPI1_REMAP BIT(0)
|
||||
|
||||
/* External interrupt configuration register 1 */
|
||||
|
||||
#define AFIO_EXTICR1_EXTI3 (0xF << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PA (0x0 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PB (0x1 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PC (0x2 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PD (0x3 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PE (0x4 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PF (0x5 << 12)
|
||||
#define AFIO_EXTICR1_EXTI3_PG (0x6 << 12)
|
||||
#define AFIO_EXTICR1_EXTI2 (0xF << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PA (0x0 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PB (0x1 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PC (0x2 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PD (0x3 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PE (0x4 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PF (0x5 << 8)
|
||||
#define AFIO_EXTICR1_EXTI2_PG (0x6 << 8)
|
||||
#define AFIO_EXTICR1_EXTI1 (0xF << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PA (0x0 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PB (0x1 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PC (0x2 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PD (0x3 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PE (0x4 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PF (0x5 << 4)
|
||||
#define AFIO_EXTICR1_EXTI1_PG (0x6 << 4)
|
||||
#define AFIO_EXTICR1_EXTI0 0xF
|
||||
#define AFIO_EXTICR1_EXTI0_PA 0x0
|
||||
#define AFIO_EXTICR1_EXTI0_PB 0x1
|
||||
#define AFIO_EXTICR1_EXTI0_PC 0x2
|
||||
#define AFIO_EXTICR1_EXTI0_PD 0x3
|
||||
#define AFIO_EXTICR1_EXTI0_PE 0x4
|
||||
#define AFIO_EXTICR1_EXTI0_PF 0x5
|
||||
#define AFIO_EXTICR1_EXTI0_PG 0x6
|
||||
|
||||
/* External interrupt configuration register 2 */
|
||||
|
||||
#define AFIO_EXTICR2_EXTI7 (0xF << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PA (0x0 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PB (0x1 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PC (0x2 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PD (0x3 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PE (0x4 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PF (0x5 << 12)
|
||||
#define AFIO_EXTICR2_EXTI7_PG (0x6 << 12)
|
||||
#define AFIO_EXTICR2_EXTI6 (0xF << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PA (0x0 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PB (0x1 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PC (0x2 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PD (0x3 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PE (0x4 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PF (0x5 << 8)
|
||||
#define AFIO_EXTICR2_EXTI6_PG (0x6 << 8)
|
||||
#define AFIO_EXTICR2_EXTI5 (0xF << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PA (0x0 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PB (0x1 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PC (0x2 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PD (0x3 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PE (0x4 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PF (0x5 << 4)
|
||||
#define AFIO_EXTICR2_EXTI5_PG (0x6 << 4)
|
||||
#define AFIO_EXTICR2_EXTI4 0xF
|
||||
#define AFIO_EXTICR2_EXTI4_PA 0x0
|
||||
#define AFIO_EXTICR2_EXTI4_PB 0x1
|
||||
#define AFIO_EXTICR2_EXTI4_PC 0x2
|
||||
#define AFIO_EXTICR2_EXTI4_PD 0x3
|
||||
#define AFIO_EXTICR2_EXTI4_PE 0x4
|
||||
#define AFIO_EXTICR2_EXTI4_PF 0x5
|
||||
#define AFIO_EXTICR2_EXTI4_PG 0x6
|
||||
|
||||
/* AF remap and debug I/O configuration register 2 */
|
||||
|
||||
#define AFIO_MAPR2_FSMC_NADV BIT(10)
|
||||
#define AFIO_MAPR2_TIM14_REMAP BIT(9)
|
||||
#define AFIO_MAPR2_TIM13_REMAP BIT(8)
|
||||
#define AFIO_MAPR2_TIM11_REMAP BIT(7)
|
||||
#define AFIO_MAPR2_TIM10_REMAP BIT(6)
|
||||
#define AFIO_MAPR2_TIM9_REMAP BIT(5)
|
||||
|
||||
/*
|
||||
* AFIO convenience routines
|
||||
*/
|
||||
|
||||
void afio_init(void);
|
||||
|
||||
/**
|
||||
* External interrupt line numbers.
|
||||
*/
|
||||
typedef enum afio_exti_num {
|
||||
AFIO_EXTI_0, /**< External interrupt line 0. */
|
||||
AFIO_EXTI_1, /**< External interrupt line 1. */
|
||||
AFIO_EXTI_2, /**< External interrupt line 2. */
|
||||
AFIO_EXTI_3, /**< External interrupt line 3. */
|
||||
AFIO_EXTI_4, /**< External interrupt line 4. */
|
||||
AFIO_EXTI_5, /**< External interrupt line 5. */
|
||||
AFIO_EXTI_6, /**< External interrupt line 6. */
|
||||
AFIO_EXTI_7, /**< External interrupt line 7. */
|
||||
AFIO_EXTI_8, /**< External interrupt line 8. */
|
||||
AFIO_EXTI_9, /**< External interrupt line 9. */
|
||||
AFIO_EXTI_10, /**< External interrupt line 10. */
|
||||
AFIO_EXTI_11, /**< External interrupt line 11. */
|
||||
AFIO_EXTI_12, /**< External interrupt line 12. */
|
||||
AFIO_EXTI_13, /**< External interrupt line 13. */
|
||||
AFIO_EXTI_14, /**< External interrupt line 14. */
|
||||
AFIO_EXTI_15, /**< External interrupt line 15. */
|
||||
} afio_exti_num;
|
||||
|
||||
void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port);
|
||||
|
||||
/* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and
|
||||
* not used in either MAPR or MAPR2 */
|
||||
#define AFIO_REMAP_USE_MAPR2 (1 << 31)
|
||||
|
||||
/**
|
||||
* @brief Available peripheral remaps.
|
||||
* @see afio_remap()
|
||||
*/
|
||||
typedef enum afio_remap_peripheral {
|
||||
AFIO_REMAP_ADC2_ETRGREG = AFIO_MAPR_ADC2_ETRGREG_REMAP, /**<
|
||||
ADC 2 external trigger regular conversion remapping */
|
||||
AFIO_REMAP_ADC2_ETRGINJ = AFIO_MAPR_ADC2_ETRGINJ_REMAP, /**<
|
||||
ADC 2 external trigger injected conversion remapping */
|
||||
AFIO_REMAP_ADC1_ETRGREG = AFIO_MAPR_ADC1_ETRGREG_REMAP, /**<
|
||||
ADC 1 external trigger regular conversion remapping */
|
||||
AFIO_REMAP_ADC1_ETRGINJ = AFIO_MAPR_ADC1_ETRGINJ_REMAP, /**<
|
||||
ADC 1 external trigger injected conversion remapping */
|
||||
AFIO_REMAP_TIM5CH4_I = AFIO_MAPR_TIM5CH4_IREMAP, /**<
|
||||
Timer 5 channel 4 internal remapping */
|
||||
AFIO_REMAP_PD01 = AFIO_MAPR_PD01_REMAP, /**<
|
||||
Port D0/Port D1 mapping on OSC_IN/OSC_OUT */
|
||||
AFIO_REMAP_CAN_1 = AFIO_MAPR_CAN_REMAP_PB8_PB9, /**<
|
||||
CAN alternate function remapping 1 (RX on PB8, TX on PB9) */
|
||||
AFIO_REMAP_CAN_2 = AFIO_MAPR_CAN_REMAP_PD0_PD1, /**<
|
||||
CAN alternate function remapping 2 (RX on PD0, TX on PD1) */
|
||||
AFIO_REMAP_TIM4 = AFIO_MAPR_TIM4_REMAP, /**<
|
||||
Timer 4 remapping */
|
||||
AFIO_REMAP_TIM3_PARTIAL = AFIO_MAPR_TIM3_REMAP_PARTIAL, /**<
|
||||
Timer 3 partial remapping */
|
||||
AFIO_REMAP_TIM3_FULL = AFIO_MAPR_TIM3_REMAP_FULL, /**<
|
||||
Timer 3 full remapping */
|
||||
AFIO_REMAP_TIM2_PARTIAL_1 = AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3, /**<
|
||||
Timer 2 partial remapping 1 (CH1 and ETR on PA15, CH2 on PB3, CH3
|
||||
on PA2, CH4 on PA3) */
|
||||
AFIO_REMAP_TIM2_PARTIAL_2 = AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11, /**<
|
||||
Timer 2 partial remapping 2 (CH1 and ETR on PA0, CH2 on PA1, CH3
|
||||
on PB10, CH4 on PB11) */
|
||||
AFIO_REMAP_TIM2_FULL = AFIO_MAPR_TIM2_REMAP_FULL, /**<
|
||||
Timer 2 full remapping */
|
||||
AFIO_REMAP_USART2 = AFIO_MAPR_USART2_REMAP, /**<
|
||||
USART 2 remapping */
|
||||
AFIO_REMAP_USART1 = AFIO_MAPR_USART1_REMAP, /**<
|
||||
USART 1 remapping */
|
||||
AFIO_REMAP_I2C1 = AFIO_MAPR_I2C1_REMAP, /**<
|
||||
I2C 1 remapping */
|
||||
AFIO_REMAP_SPI1 = AFIO_MAPR_SPI1_REMAP, /**<
|
||||
SPI 1 remapping */
|
||||
AFIO_REMAP_FSMC_NADV = (AFIO_MAPR2_FSMC_NADV |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
NADV signal not connected */
|
||||
AFIO_REMAP_TIM14 = (AFIO_MAPR2_TIM14_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 14 remapping */
|
||||
AFIO_REMAP_TIM13 = (AFIO_MAPR2_TIM13_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 13 remapping */
|
||||
AFIO_REMAP_TIM11 = (AFIO_MAPR2_TIM11_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 11 remapping */
|
||||
AFIO_REMAP_TIM10 = (AFIO_MAPR2_TIM10_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2), /**<
|
||||
Timer 10 remapping */
|
||||
AFIO_REMAP_TIM9 = (AFIO_MAPR2_TIM9_REMAP |
|
||||
AFIO_REMAP_USE_MAPR2) /**<
|
||||
Timer 9 */
|
||||
} afio_remap_peripheral;
|
||||
|
||||
void afio_remap(afio_remap_peripheral p);
|
||||
|
||||
/**
|
||||
* @brief Debug port configuration
|
||||
*
|
||||
* Used to configure the behavior of JTAG and Serial Wire (SW) debug
|
||||
* ports and their associated GPIO pins.
|
||||
*
|
||||
* @see afio_cfg_debug_ports()
|
||||
*/
|
||||
typedef enum afio_debug_cfg {
|
||||
AFIO_DEBUG_FULL_SWJ = AFIO_MAPR_SWJ_CFG_FULL_SWJ, /**<
|
||||
Full Serial Wire and JTAG debug */
|
||||
AFIO_DEBUG_FULL_SWJ_NO_NJRST = AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST, /**<
|
||||
Full Serial Wire and JTAG, but no NJTRST. */
|
||||
AFIO_DEBUG_SW_ONLY = AFIO_MAPR_SWJ_CFG_NO_JTAG_SW, /**<
|
||||
Serial Wire debug only (JTAG-DP disabled,
|
||||
SW-DP enabled) */
|
||||
AFIO_DEBUG_NONE = AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW /**<
|
||||
No debug; all JTAG and SW pins are free
|
||||
for use as GPIOs. */
|
||||
} afio_debug_cfg;
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the JTAG and SW debug ports.
|
||||
* @param config Desired debug port configuration
|
||||
* @see afio_debug_cfg
|
||||
*/
|
||||
static inline void afio_cfg_debug_ports(afio_debug_cfg config) {
|
||||
//__io uint32 *mapr = &AFIO_BASE->MAPR;
|
||||
//*mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,565 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file i2c.c
|
||||
* @brief Inter-Integrated Circuit (I2C) support.
|
||||
*
|
||||
* Currently, only master mode is supported.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "rcc.h"
|
||||
#include "gpio.h"
|
||||
#include "nvic.h"
|
||||
#include "i2c.h"
|
||||
#include "string.h"
|
||||
#include "systick.h"
|
||||
|
||||
static i2c_dev i2c_dev1 = {
|
||||
.regs = I2C1_BASE,
|
||||
.gpio_port = &gpiob,
|
||||
.sda_pin = 7,
|
||||
.scl_pin = 6,
|
||||
.clk_id = RCC_I2C1,
|
||||
.ev_nvic_line = NVIC_I2C1_EV,
|
||||
.er_nvic_line = NVIC_I2C1_ER,
|
||||
.state = I2C_STATE_DISABLED
|
||||
};
|
||||
/** I2C1 device */
|
||||
i2c_dev* const I2C1 = &i2c_dev1;
|
||||
|
||||
static i2c_dev i2c_dev2 = {
|
||||
.regs = I2C2_BASE,
|
||||
.gpio_port = &gpiob,
|
||||
.sda_pin = 11,
|
||||
.scl_pin = 10,
|
||||
.clk_id = RCC_I2C2,
|
||||
.ev_nvic_line = NVIC_I2C2_EV,
|
||||
.er_nvic_line = NVIC_I2C2_ER,
|
||||
.state = I2C_STATE_DISABLED
|
||||
};
|
||||
/** I2C2 device */
|
||||
i2c_dev* const I2C2 = &i2c_dev2;
|
||||
|
||||
static inline int32 wait_for_state_change(i2c_dev *dev,
|
||||
i2c_state state,
|
||||
uint32 timeout);
|
||||
|
||||
/**
|
||||
* @brief Fill data register with slave address
|
||||
* @param dev I2C device
|
||||
* @param addr Slave address
|
||||
* @param rw Read/write bit
|
||||
*/
|
||||
static inline void i2c_send_slave_addr(i2c_dev *dev, uint32 addr, uint32 rw) {
|
||||
dev->regs->DR = (addr << 1) | rw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple debugging trail. Define I2C_DEBUG to turn on.
|
||||
*/
|
||||
#ifdef I2C_DEBUG
|
||||
|
||||
#define NR_CRUMBS 128
|
||||
static struct crumb crumbs[NR_CRUMBS];
|
||||
static uint32 cur_crumb = 0;
|
||||
|
||||
static inline void i2c_drop_crumb(uint32 event, uint32 arg0, uint32 arg1) {
|
||||
if (cur_crumb < NR_CRUMBS) {
|
||||
struct crumb *crumb = &crumbs[cur_crumb++];
|
||||
crumb->event = event;
|
||||
crumb->arg0 = arg0;
|
||||
crumb->arg1 = arg1;
|
||||
}
|
||||
}
|
||||
#define I2C_CRUMB(event, arg0, arg1) i2c_drop_crumb(event, arg0, arg1)
|
||||
|
||||
#else
|
||||
#define I2C_CRUMB(event, arg0, arg1)
|
||||
#endif
|
||||
|
||||
struct crumb {
|
||||
uint32 event;
|
||||
uint32 arg0;
|
||||
uint32 arg1;
|
||||
};
|
||||
|
||||
enum {
|
||||
IRQ_ENTRY = 1,
|
||||
TXE_ONLY = 2,
|
||||
TXE_BTF = 3,
|
||||
STOP_SENT = 4,
|
||||
TEST = 5,
|
||||
RX_ADDR_START = 6,
|
||||
RX_ADDR_STOP = 7,
|
||||
RXNE_ONLY = 8,
|
||||
RXNE_SENDING = 9,
|
||||
RXNE_START_SENT = 10,
|
||||
RXNE_STOP_SENT = 11,
|
||||
RXNE_DONE = 12,
|
||||
ERROR_ENTRY = 13,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief IRQ handler for I2C master. Handles transmission/reception.
|
||||
* @param dev I2C device
|
||||
*/
|
||||
static void i2c_irq_handler(i2c_dev *dev) {
|
||||
i2c_msg *msg = dev->msg;
|
||||
|
||||
uint8 read = msg->flags & I2C_MSG_READ;
|
||||
|
||||
uint32 sr1 = dev->regs->SR1;
|
||||
uint32 sr2 = dev->regs->SR2;
|
||||
I2C_CRUMB(IRQ_ENTRY, sr1, sr2);
|
||||
|
||||
/*
|
||||
* Reset timeout counter
|
||||
*/
|
||||
dev->timestamp = systick_uptime();
|
||||
|
||||
/*
|
||||
* EV5: Start condition sent
|
||||
*/
|
||||
if (sr1 & I2C_SR1_SB) {
|
||||
msg->xferred = 0;
|
||||
i2c_enable_irq(dev, I2C_IRQ_BUFFER);
|
||||
|
||||
/*
|
||||
* Master receiver
|
||||
*/
|
||||
if (read) {
|
||||
i2c_enable_ack(dev);
|
||||
}
|
||||
|
||||
i2c_send_slave_addr(dev, msg->addr, read);
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV6: Slave address sent
|
||||
*/
|
||||
if (sr1 & I2C_SR1_ADDR) {
|
||||
/*
|
||||
* Special case event EV6_1 for master receiver.
|
||||
* Generate NACK and restart/stop condition after ADDR
|
||||
* is cleared.
|
||||
*/
|
||||
if (read) {
|
||||
if (msg->length == 1) {
|
||||
i2c_disable_ack(dev);
|
||||
if (dev->msgs_left > 1) {
|
||||
i2c_start_condition(dev);
|
||||
I2C_CRUMB(RX_ADDR_START, 0, 0);
|
||||
} else {
|
||||
i2c_stop_condition(dev);
|
||||
I2C_CRUMB(RX_ADDR_STOP, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Master transmitter: write first byte to fill shift
|
||||
* register. We should get another TXE interrupt
|
||||
* immediately to fill DR again.
|
||||
*/
|
||||
if (msg->length != 1) {
|
||||
i2c_write(dev, msg->data[msg->xferred++]);
|
||||
}
|
||||
}
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV8: Master transmitter
|
||||
* Transmit buffer empty, but we haven't finished transmitting the last
|
||||
* byte written.
|
||||
*/
|
||||
if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) {
|
||||
I2C_CRUMB(TXE_ONLY, 0, 0);
|
||||
if (dev->msgs_left) {
|
||||
i2c_write(dev, msg->data[msg->xferred++]);
|
||||
if (msg->xferred == msg->length) {
|
||||
/*
|
||||
* End of this message. Turn off TXE/RXNE and wait for
|
||||
* BTF to send repeated start or stop condition.
|
||||
*/
|
||||
i2c_disable_irq(dev, I2C_IRQ_BUFFER);
|
||||
dev->msgs_left--;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This should be impossible...
|
||||
*/
|
||||
throb();
|
||||
}
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV8_2: Master transmitter
|
||||
* Last byte sent, program repeated start/stop
|
||||
*/
|
||||
if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) {
|
||||
I2C_CRUMB(TXE_BTF, 0, 0);
|
||||
if (dev->msgs_left) {
|
||||
I2C_CRUMB(TEST, 0, 0);
|
||||
/*
|
||||
* Repeated start insanity: We can't disable ITEVTEN or else SB
|
||||
* won't interrupt, but if we don't disable ITEVTEN, BTF will
|
||||
* continually interrupt us. What the fuck ST?
|
||||
*/
|
||||
i2c_start_condition(dev);
|
||||
while (!(dev->regs->SR1 & I2C_SR1_SB))
|
||||
;
|
||||
dev->msg++;
|
||||
} else {
|
||||
i2c_stop_condition(dev);
|
||||
|
||||
/*
|
||||
* Turn off event interrupts to keep BTF from firing until
|
||||
* the end of the stop condition. Why on earth they didn't
|
||||
* have a start/stop condition request clear BTF is beyond
|
||||
* me.
|
||||
*/
|
||||
i2c_disable_irq(dev, I2C_IRQ_EVENT);
|
||||
I2C_CRUMB(STOP_SENT, 0, 0);
|
||||
dev->state = I2C_STATE_XFER_DONE;
|
||||
}
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV7: Master Receiver
|
||||
*/
|
||||
if (sr1 & I2C_SR1_RXNE) {
|
||||
I2C_CRUMB(RXNE_ONLY, 0, 0);
|
||||
msg->data[msg->xferred++] = dev->regs->DR;
|
||||
|
||||
/*
|
||||
* EV7_1: Second to last byte in the reception? Set NACK and generate
|
||||
* stop/restart condition in time for the last byte. We'll get one more
|
||||
* RXNE interrupt before shutting things down.
|
||||
*/
|
||||
if (msg->xferred == (msg->length - 1)) {
|
||||
i2c_disable_ack(dev);
|
||||
if (dev->msgs_left > 2) {
|
||||
i2c_start_condition(dev);
|
||||
I2C_CRUMB(RXNE_START_SENT, 0, 0);
|
||||
} else {
|
||||
i2c_stop_condition(dev);
|
||||
I2C_CRUMB(RXNE_STOP_SENT, 0, 0);
|
||||
}
|
||||
} else if (msg->xferred == msg->length) {
|
||||
dev->msgs_left--;
|
||||
if (dev->msgs_left == 0) {
|
||||
/*
|
||||
* We're done.
|
||||
*/
|
||||
I2C_CRUMB(RXNE_DONE, 0, 0);
|
||||
dev->state = I2C_STATE_XFER_DONE;
|
||||
} else {
|
||||
dev->msg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __irq_i2c1_ev(void) {
|
||||
i2c_irq_handler(&i2c_dev1);
|
||||
}
|
||||
|
||||
void __irq_i2c2_ev(void) {
|
||||
i2c_irq_handler(&i2c_dev2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interrupt handler for I2C error conditions
|
||||
* @param dev I2C device
|
||||
* @sideeffect Aborts any pending I2C transactions
|
||||
*/
|
||||
static void i2c_irq_error_handler(i2c_dev *dev) {
|
||||
I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2);
|
||||
|
||||
dev->error_flags = dev->regs->SR2 & (I2C_SR1_BERR |
|
||||
I2C_SR1_ARLO |
|
||||
I2C_SR1_AF |
|
||||
I2C_SR1_OVR);
|
||||
/* Clear flags */
|
||||
dev->regs->SR1 = 0;
|
||||
dev->regs->SR2 = 0;
|
||||
|
||||
i2c_stop_condition(dev);
|
||||
i2c_disable_irq(dev, I2C_IRQ_BUFFER | I2C_IRQ_EVENT | I2C_IRQ_ERROR);
|
||||
dev->state = I2C_STATE_ERROR;
|
||||
}
|
||||
|
||||
void __irq_i2c1_er(void) {
|
||||
i2c_irq_error_handler(&i2c_dev1);
|
||||
}
|
||||
|
||||
void __irq_i2c2_er(void) {
|
||||
i2c_irq_error_handler(&i2c_dev2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset an I2C bus.
|
||||
*
|
||||
* Reset is accomplished by clocking out pulses until any hung slaves
|
||||
* release SDA and SCL, then generating a START condition, then a STOP
|
||||
* condition.
|
||||
*
|
||||
* @param dev I2C device
|
||||
*/
|
||||
void i2c_bus_reset(const i2c_dev *dev) {
|
||||
/* Release both lines */
|
||||
gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
|
||||
gpio_write_bit(dev->gpio_port, dev->sda_pin, 1);
|
||||
gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_OUTPUT_OD);
|
||||
gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_OUTPUT_OD);
|
||||
|
||||
/*
|
||||
* Make sure the bus is free by clocking it until any slaves release the
|
||||
* bus.
|
||||
*/
|
||||
while (!gpio_read_bit(dev->gpio_port, dev->sda_pin)) {
|
||||
/* Wait for any clock stretching to finish */
|
||||
while (!gpio_read_bit(dev->gpio_port, dev->scl_pin))
|
||||
;
|
||||
delay_us(10);
|
||||
|
||||
/* Pull low */
|
||||
gpio_write_bit(dev->gpio_port, dev->scl_pin, 0);
|
||||
delay_us(10);
|
||||
|
||||
/* Release high again */
|
||||
gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
|
||||
delay_us(10);
|
||||
}
|
||||
|
||||
/* Generate start then stop condition */
|
||||
gpio_write_bit(dev->gpio_port, dev->sda_pin, 0);
|
||||
delay_us(10);
|
||||
gpio_write_bit(dev->gpio_port, dev->scl_pin, 0);
|
||||
delay_us(10);
|
||||
gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
|
||||
delay_us(10);
|
||||
gpio_write_bit(dev->gpio_port, dev->sda_pin, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize an I2C device and reset its registers to their
|
||||
* default values.
|
||||
* @param dev Device to initialize.
|
||||
*/
|
||||
void i2c_init(i2c_dev *dev) {
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize an I2C device as bus master
|
||||
* @param dev Device to enable
|
||||
* @param flags Bitwise or of the following I2C options:
|
||||
* I2C_FAST_MODE: 400 khz operation,
|
||||
* I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for
|
||||
* fast mode),
|
||||
* I2C_BUS_RESET: Reset the bus and clock out any hung slaves on
|
||||
* initialization,
|
||||
* I2C_10BIT_ADDRESSING: Enable 10-bit addressing,
|
||||
* I2C_REMAP: Remap I2C1 to SCL/PB8 SDA/PB9.
|
||||
*/
|
||||
void i2c_master_enable(i2c_dev *dev, uint32 flags) {
|
||||
#define I2C_CLK (STM32_PCLK1/1000000)
|
||||
uint32 ccr = 0;
|
||||
uint32 trise = 0;
|
||||
|
||||
/* PE must be disabled to configure the device */
|
||||
ASSERT(!(dev->regs->CR1 & I2C_CR1_PE));
|
||||
|
||||
if ((dev == I2C1) && (flags & I2C_REMAP)) {
|
||||
afio_remap(AFIO_REMAP_I2C1);
|
||||
I2C1->sda_pin = 9;
|
||||
I2C1->scl_pin = 8;
|
||||
}
|
||||
|
||||
/* Reset the bus. Clock out any hung slaves. */
|
||||
if (flags & I2C_BUS_RESET) {
|
||||
i2c_bus_reset(dev);
|
||||
}
|
||||
|
||||
/* Turn on clock and set GPIO modes */
|
||||
i2c_init(dev);
|
||||
gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_AF_OUTPUT_OD);
|
||||
gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_AF_OUTPUT_OD);
|
||||
|
||||
/* I2C1 and I2C2 are fed from APB1, clocked at 36MHz */
|
||||
i2c_set_input_clk(dev, I2C_CLK);
|
||||
|
||||
if (flags & I2C_FAST_MODE) {
|
||||
ccr |= I2C_CCR_FS;
|
||||
|
||||
if (flags & I2C_DUTY_16_9) {
|
||||
/* Tlow/Thigh = 16/9 */
|
||||
ccr |= I2C_CCR_DUTY;
|
||||
ccr |= STM32_PCLK1/(400000 * 25);
|
||||
} else {
|
||||
/* Tlow/Thigh = 2 */
|
||||
ccr |= STM32_PCLK1/(400000 * 3);
|
||||
}
|
||||
|
||||
trise = (300 * (I2C_CLK)/1000) + 1;
|
||||
} else {
|
||||
/* Tlow/Thigh = 1 */
|
||||
ccr = STM32_PCLK1/(100000 * 2);
|
||||
trise = I2C_CLK + 1;
|
||||
}
|
||||
|
||||
/* Set minimum required value if CCR < 1*/
|
||||
if ((ccr & I2C_CCR_CCR) == 0) {
|
||||
ccr |= 0x1;
|
||||
}
|
||||
|
||||
i2c_set_clk_control(dev, ccr);
|
||||
i2c_set_trise(dev, trise);
|
||||
|
||||
/* Enable event and buffer interrupts */
|
||||
nvic_irq_enable(dev->ev_nvic_line);
|
||||
nvic_irq_enable(dev->er_nvic_line);
|
||||
i2c_enable_irq(dev, I2C_IRQ_EVENT | I2C_IRQ_BUFFER | I2C_IRQ_ERROR);
|
||||
|
||||
/*
|
||||
* Important STM32 Errata:
|
||||
*
|
||||
* See STM32F10xx8 and STM32F10xxB Errata sheet (Doc ID 14574 Rev 8),
|
||||
* Section 2.11.1, 2.11.2.
|
||||
*
|
||||
* 2.11.1:
|
||||
* When the EV7, EV7_1, EV6_1, EV6_3, EV2, EV8, and EV3 events are not
|
||||
* managed before the current byte is being transferred, problems may be
|
||||
* encountered such as receiving an extra byte, reading the same data twice
|
||||
* or missing data.
|
||||
*
|
||||
* 2.11.2:
|
||||
* In Master Receiver mode, when closing the communication using
|
||||
* method 2, the content of the last read data can be corrupted.
|
||||
*
|
||||
* If the user software is not able to read the data N-1 before the STOP
|
||||
* condition is generated on the bus, the content of the shift register
|
||||
* (data N) will be corrupted. (data N is shifted 1-bit to the left).
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* In order to ensure that events are not missed, the i2c interrupt must
|
||||
* not be preempted. We set the i2c interrupt priority to be the highest
|
||||
* interrupt in the system (priority level 0). All other interrupts have
|
||||
* been initialized to priority level 16. See nvic_init().
|
||||
*/
|
||||
nvic_irq_set_priority(dev->ev_nvic_line, 0);
|
||||
nvic_irq_set_priority(dev->er_nvic_line, 0);
|
||||
|
||||
/* Make it go! */
|
||||
i2c_peripheral_enable(dev);
|
||||
|
||||
dev->state = I2C_STATE_IDLE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Process an i2c transaction.
|
||||
*
|
||||
* Transactions are composed of one or more i2c_msg's, and may be read
|
||||
* or write tranfers. Multiple i2c_msg's will generate a repeated
|
||||
* start in between messages.
|
||||
*
|
||||
* @param dev I2C device
|
||||
* @param msgs Messages to send/receive
|
||||
* @param num Number of messages to send/receive
|
||||
* @param timeout Bus idle timeout in milliseconds before aborting the
|
||||
* transfer. 0 denotes no timeout.
|
||||
* @return 0 on success,
|
||||
* I2C_ERROR_PROTOCOL if there was a protocol error,
|
||||
* I2C_ERROR_TIMEOUT if the transfer timed out.
|
||||
*/
|
||||
int32 i2c_master_xfer(i2c_dev *dev,
|
||||
i2c_msg *msgs,
|
||||
uint16 num,
|
||||
uint32 timeout) {
|
||||
int32 rc;
|
||||
|
||||
ASSERT(dev->state == I2C_STATE_IDLE);
|
||||
|
||||
dev->msg = msgs;
|
||||
dev->msgs_left = num;
|
||||
dev->timestamp = systick_uptime();
|
||||
dev->state = I2C_STATE_BUSY;
|
||||
|
||||
i2c_enable_irq(dev, I2C_IRQ_EVENT);
|
||||
i2c_start_condition(dev);
|
||||
|
||||
rc = wait_for_state_change(dev, I2C_STATE_XFER_DONE, timeout);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->state = I2C_STATE_IDLE;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wait for an I2C event, or time out in case of error.
|
||||
* @param dev I2C device
|
||||
* @param state I2C_state state to wait for
|
||||
* @param timeout Timeout, in milliseconds
|
||||
* @return 0 if target state is reached, a negative value on error.
|
||||
*/
|
||||
static inline int32 wait_for_state_change(i2c_dev *dev,
|
||||
i2c_state state,
|
||||
uint32 timeout) {
|
||||
i2c_state tmp;
|
||||
|
||||
while (1) {
|
||||
tmp = dev->state;
|
||||
|
||||
if (tmp == I2C_STATE_ERROR) {
|
||||
return I2C_STATE_ERROR;
|
||||
}
|
||||
|
||||
if (tmp == state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
if (systick_uptime() > (dev->timestamp + timeout)) {
|
||||
/* TODO: overflow? */
|
||||
/* TODO: racy? */
|
||||
return I2C_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,348 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file i2c.h
|
||||
* @brief Inter-Integrated Circuit (I2C) peripheral support
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#ifndef _I2C_H_
|
||||
#define _I2C_H_
|
||||
|
||||
/** I2C register map type */
|
||||
typedef struct i2c_reg_map {
|
||||
__io uint32 CR1; /**< Control register 1 */
|
||||
__io uint32 CR2; /**< Control register 2 */
|
||||
__io uint32 OAR1; /**< Own address register 1 */
|
||||
__io uint32 OAR2; /**< Own address register 2 */
|
||||
__io uint32 DR; /**< Data register */
|
||||
__io uint32 SR1; /**< Status register 1 */
|
||||
__io uint32 SR2; /**< Status register 2 */
|
||||
__io uint32 CCR; /**< Clock control register */
|
||||
__io uint32 TRISE; /**< TRISE (rise time) register */
|
||||
} i2c_reg_map;
|
||||
|
||||
/** I2C device states */
|
||||
typedef enum i2c_state {
|
||||
I2C_STATE_DISABLED = 0, /**< Disabled */
|
||||
I2C_STATE_IDLE = 1, /**< Idle */
|
||||
I2C_STATE_XFER_DONE = 2, /**< Done with transfer */
|
||||
I2C_STATE_BUSY = 3, /**< Busy */
|
||||
I2C_STATE_ERROR = -1 /**< Error occurred */
|
||||
} i2c_state;
|
||||
|
||||
/**
|
||||
* @brief I2C message type
|
||||
*/
|
||||
typedef struct i2c_msg {
|
||||
uint16 addr; /**< Address */
|
||||
#define I2C_MSG_READ 0x1
|
||||
#define I2C_MSG_10BIT_ADDR 0x2
|
||||
uint16 flags; /**< Bitwise OR of I2C_MSG_READ and
|
||||
I2C_MSG_10BIT_ADDR */
|
||||
uint16 length; /**< Message length */
|
||||
uint16 xferred; /**< Messages transferred */
|
||||
uint8 *data; /**< Data */
|
||||
} i2c_msg;
|
||||
|
||||
/**
|
||||
* @brief I2C device type.
|
||||
*/
|
||||
typedef struct i2c_dev {
|
||||
i2c_reg_map *regs; /**< Register map */
|
||||
gpio_dev *gpio_port; /**< SDA, SCL pins' GPIO port */
|
||||
uint8 sda_pin; /**< SDA bit on gpio_port */
|
||||
uint8 scl_pin; /**< SCL bit on gpio_port */
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
nvic_irq_num ev_nvic_line; /**< Event IRQ number */
|
||||
nvic_irq_num er_nvic_line; /**< Error IRQ number */
|
||||
volatile i2c_state state; /**< Device state */
|
||||
uint16 msgs_left; /**< Messages left */
|
||||
i2c_msg *msg; /**< Messages */
|
||||
volatile uint32 timestamp; /**< For internal use */
|
||||
uint32 error_flags; /**< Error flags, set on I2C error condition */
|
||||
} i2c_dev;
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
extern i2c_dev* const I2C1;
|
||||
extern i2c_dev* const I2C2;
|
||||
|
||||
/*
|
||||
* Register map base pointers
|
||||
*/
|
||||
|
||||
/** I2C1 register map base pointer */
|
||||
#define I2C1_BASE ((struct i2c_reg_map*)0x40005400)
|
||||
/** I2C2 register map base pointer */
|
||||
#define I2C2_BASE ((struct i2c_reg_map*)0x40005800)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Control register 1 */
|
||||
|
||||
#define I2C_CR1_SWRST BIT(15) // Software reset
|
||||
#define I2C_CR1_ALERT BIT(13) // SMBus alert
|
||||
#define I2C_CR1_PEC BIT(12) // Packet error checking
|
||||
#define I2C_CR1_POS BIT(11) // Acknowledge/PEC position
|
||||
#define I2C_CR1_ACK BIT(10) // Acknowledge enable
|
||||
#define I2C_CR1_START BIT(8) // Start generation
|
||||
#define I2C_CR1_STOP BIT(9) // Stop generation
|
||||
#define I2C_CR1_PE BIT(0) // Peripheral Enable
|
||||
|
||||
/* Control register 2 */
|
||||
|
||||
#define I2C_CR2_LAST BIT(12) // DMA last transfer
|
||||
#define I2C_CR2_DMAEN BIT(11) // DMA requests enable
|
||||
#define I2C_CR2_ITBUFEN BIT(10) // Buffer interrupt enable
|
||||
#define I2C_CR2_ITEVTEN BIT(9) // Event interupt enable
|
||||
#define I2C_CR2_ITERREN BIT(8) // Error interupt enable
|
||||
#define I2C_CR2_FREQ 0xFFF // Peripheral input frequency
|
||||
|
||||
/* Clock control register */
|
||||
|
||||
#define I2C_CCR_FS BIT(15) // Fast mode selection
|
||||
#define I2C_CCR_DUTY BIT(14) // 16/9 duty ratio
|
||||
#define I2C_CCR_CCR 0xFFF // Clock control bits
|
||||
|
||||
/* Status register 1 */
|
||||
|
||||
#define I2C_SR1_SB BIT(0) // Start bit
|
||||
#define I2C_SR1_ADDR BIT(1) // Address sent/matched
|
||||
#define I2C_SR1_BTF BIT(2) // Byte transfer finished
|
||||
#define I2C_SR1_ADD10 BIT(3) // 10-bit header sent
|
||||
#define I2C_SR1_STOPF BIT(4) // Stop detection
|
||||
#define I2C_SR1_RXNE BIT(6) // Data register not empty
|
||||
#define I2C_SR1_TXE BIT(7) // Data register empty
|
||||
#define I2C_SR1_BERR BIT(8) // Bus error
|
||||
#define I2C_SR1_ARLO BIT(9) // Arbitration lost
|
||||
#define I2C_SR1_AF BIT(10) // Acknowledge failure
|
||||
#define I2C_SR1_OVR BIT(11) // Overrun/underrun
|
||||
#define I2C_SR1_PECERR BIT(12) // PEC Error in reception
|
||||
#define I2C_SR1_TIMEOUT BIT(14) // Timeout or Tlow error
|
||||
#define I2C_SR1_SMBALERT BIT(15) // SMBus alert
|
||||
|
||||
/* Status register 2 */
|
||||
|
||||
#define I2C_SR2_MSL BIT(0) // Master/slave
|
||||
#define I2C_SR2_BUSY BIT(1) // Bus busy
|
||||
#define I2C_SR2_TRA BIT(2) // Transmitter/receiver
|
||||
#define I2C_SR2_GENCALL BIT(4) // General call address
|
||||
#define I2C_SR2_SMBDEFAULT BIT(5) // SMBus device default address
|
||||
#define I2C_SR2_SMBHOST BIT(6) // SMBus host header
|
||||
#define I2C_SR2_DUALF BIT(7) // Dual flag
|
||||
#define I2C_SR2_PEC 0xFF00 // Packet error checking register
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void i2c_init(i2c_dev *dev);
|
||||
|
||||
/* I2C enable options */
|
||||
#define I2C_FAST_MODE BIT(0) // 400 khz
|
||||
#define I2C_DUTY_16_9 BIT(1) // 16/9 duty ratio
|
||||
#define I2C_REMAP BIT(2) // Use alternate pin mapping
|
||||
#define I2C_BUS_RESET BIT(3) // Perform a bus reset
|
||||
void i2c_master_enable(i2c_dev *dev, uint32 flags);
|
||||
|
||||
#define I2C_ERROR_PROTOCOL (-1)
|
||||
#define I2C_ERROR_TIMEOUT (-2)
|
||||
int32 i2c_master_xfer(i2c_dev *dev, i2c_msg *msgs, uint16 num, uint32 timeout);
|
||||
|
||||
void i2c_bus_reset(const i2c_dev *dev);
|
||||
|
||||
/**
|
||||
* @brief Disable an I2C device
|
||||
*
|
||||
* This function disables the corresponding peripheral and marks dev's
|
||||
* state as I2C_STATE_DISABLED.
|
||||
*
|
||||
* @param dev Device to disable.
|
||||
*/
|
||||
static inline void i2c_disable(i2c_dev *dev) {
|
||||
dev->regs->CR1 &= ~I2C_CR1_PE;
|
||||
dev->state = I2C_STATE_DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn on an I2C peripheral
|
||||
* @param dev Device to enable
|
||||
*/
|
||||
static inline void i2c_peripheral_enable(i2c_dev *dev) {
|
||||
dev->regs->CR1 |= I2C_CR1_PE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn off an I2C peripheral
|
||||
* @param dev Device to turn off
|
||||
*/
|
||||
static inline void i2c_peripheral_disable(i2c_dev *dev) {
|
||||
dev->regs->CR1 &= ~I2C_CR1_PE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill transmit register
|
||||
* @param dev I2C device
|
||||
* @param byte Byte to write
|
||||
*/
|
||||
static inline void i2c_write(i2c_dev *dev, uint8 byte) {
|
||||
dev->regs->DR = byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set input clock frequency, in MHz
|
||||
* @param dev I2C device
|
||||
* @param freq Frequency in megahertz (2-36)
|
||||
*/
|
||||
static inline void i2c_set_input_clk(i2c_dev *dev, uint32 freq) {
|
||||
uint32 cr2 = dev->regs->CR2;
|
||||
cr2 &= ~I2C_CR2_FREQ;
|
||||
cr2 |= freq;
|
||||
dev->regs->CR2 = freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2C clock control register. See RM008
|
||||
* @param dev I2C device
|
||||
* @param val Value to use for clock control register (in
|
||||
* Fast/Standard mode)
|
||||
*/
|
||||
static inline void i2c_set_clk_control(i2c_dev *dev, uint32 val) {
|
||||
uint32 ccr = dev->regs->CCR;
|
||||
ccr &= ~I2C_CCR_CCR;
|
||||
ccr |= val;
|
||||
dev->regs->CCR = ccr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set SCL rise time
|
||||
* @param dev I2C device
|
||||
* @param trise Maximum rise time in fast/standard mode (see RM0008
|
||||
* for relevant formula).
|
||||
*/
|
||||
static inline void i2c_set_trise(i2c_dev *dev, uint32 trise) {
|
||||
dev->regs->TRISE = trise;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate a start condition on the bus.
|
||||
* @param dev I2C device
|
||||
*/
|
||||
static inline void i2c_start_condition(i2c_dev *dev) {
|
||||
uint32 cr1;
|
||||
while ((cr1 = dev->regs->CR1) & (I2C_CR1_START |
|
||||
I2C_CR1_STOP |
|
||||
I2C_CR1_PEC)) {
|
||||
;
|
||||
}
|
||||
dev->regs->CR1 |= I2C_CR1_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a stop condition on the bus
|
||||
* @param dev I2C device
|
||||
*/
|
||||
static inline void i2c_stop_condition(i2c_dev *dev) {
|
||||
uint32 cr1;
|
||||
while ((cr1 = dev->regs->CR1) & (I2C_CR1_START |
|
||||
I2C_CR1_STOP |
|
||||
I2C_CR1_PEC)) {
|
||||
;
|
||||
}
|
||||
dev->regs->CR1 |= I2C_CR1_STOP;
|
||||
while ((cr1 = dev->regs->CR1) & (I2C_CR1_START |
|
||||
I2C_CR1_STOP |
|
||||
I2C_CR1_PEC)) {
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable one or more I2C interrupts
|
||||
* @param dev I2C device
|
||||
* @param irqs Bitwise or of:
|
||||
* I2C_IRQ_ERROR (error interrupt),
|
||||
* I2C_IRQ_EVENT (event interrupt), and
|
||||
* I2C_IRQ_BUFFER (buffer interrupt).
|
||||
*/
|
||||
#define I2C_IRQ_ERROR I2C_CR2_ITERREN
|
||||
#define I2C_IRQ_EVENT I2C_CR2_ITEVTEN
|
||||
#define I2C_IRQ_BUFFER I2C_CR2_ITBUFEN
|
||||
static inline void i2c_enable_irq(i2c_dev *dev, uint32 irqs) {
|
||||
dev->regs->CR2 |= irqs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable one or more I2C interrupts
|
||||
* @param dev I2C device
|
||||
* @param irqs Bitwise or of:
|
||||
* I2C_IRQ_ERROR (error interrupt),
|
||||
* I2C_IRQ_EVENT (event interrupt), and
|
||||
* I2C_IRQ_BUFFER (buffer interrupt).
|
||||
*/
|
||||
static inline void i2c_disable_irq(i2c_dev *dev, uint32 irqs) {
|
||||
dev->regs->CR2 &= ~irqs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable I2C acknowledgment
|
||||
* @param dev I2C device
|
||||
*/
|
||||
static inline void i2c_enable_ack(i2c_dev *dev) {
|
||||
dev->regs->CR1 |= I2C_CR1_ACK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C acknowledgment
|
||||
* @param dev I2C device
|
||||
*/
|
||||
static inline void i2c_disable_ack(i2c_dev *dev) {
|
||||
dev->regs->CR1 &= ~I2C_CR1_ACK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* 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 iwdg.c
|
||||
* @brief Independent watchdog (IWDG) support
|
||||
*/
|
||||
|
||||
#include "iwdg.h"
|
||||
|
||||
/**
|
||||
* @brief Initialise and start the watchdog
|
||||
*
|
||||
* The prescaler and reload set the timeout. For example, a prescaler
|
||||
* of IWDG_PRE_32 divides the 40 kHz clock by 32 and gives roughly 1
|
||||
* ms per reload.
|
||||
*
|
||||
* @param prescaler Prescaler for the 40 kHz IWDG clock.
|
||||
* @param reload Independent watchdog counter reload value.
|
||||
*/
|
||||
void iwdg_init(iwdg_prescaler prescaler, uint16 reload) {
|
||||
IWDG_BASE->KR = IWDG_KR_UNLOCK;
|
||||
IWDG_BASE->PR = prescaler;
|
||||
IWDG_BASE->RLR = reload;
|
||||
|
||||
/* Start things off */
|
||||
IWDG_BASE->KR = IWDG_KR_START;
|
||||
iwdg_feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the IWDG counter.
|
||||
*
|
||||
* Calling this function will cause the IWDG counter to be reset to
|
||||
* its reload value.
|
||||
*/
|
||||
void iwdg_feed(void) {
|
||||
IWDG_BASE->KR = IWDG_KR_FEED;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* 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 iwdg.h
|
||||
* @author Michael Hope, Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Independent watchdog support.
|
||||
*
|
||||
* To use the independent watchdog, first call iwdg_init() with the
|
||||
* appropriate prescaler and IWDG counter reload values for your
|
||||
* application. Afterwards, you must periodically call iwdg_feed()
|
||||
* before the IWDG counter reaches 0 to reset the counter to its
|
||||
* reload value. If you do not, the chip will reset.
|
||||
*
|
||||
* Once started, the independent watchdog cannot be turned off.
|
||||
*/
|
||||
|
||||
#ifndef _IWDG_H_
|
||||
#define _IWDG_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register map
|
||||
*/
|
||||
|
||||
/** Independent watchdog register map type. */
|
||||
typedef struct iwdg_reg_map {
|
||||
__io uint32 KR; /**< Key register. */
|
||||
__io uint32 PR; /**< Prescaler register. */
|
||||
__io uint32 RLR; /**< Reload register. */
|
||||
__io uint32 SR; /**< Status register */
|
||||
} iwdg_reg_map;
|
||||
|
||||
/** Independent watchdog base pointer */
|
||||
#define IWDG_BASE ((struct iwdg_reg_map*)0x40003000)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Key register */
|
||||
|
||||
#define IWDG_KR_UNLOCK 0x5555
|
||||
#define IWDG_KR_FEED 0xAAAA
|
||||
#define IWDG_KR_START 0xCCCC
|
||||
|
||||
/* Prescaler register */
|
||||
|
||||
#define IWDG_PR_DIV_4 0x0
|
||||
#define IWDG_PR_DIV_8 0x1
|
||||
#define IWDG_PR_DIV_16 0x2
|
||||
#define IWDG_PR_DIV_32 0x3
|
||||
#define IWDG_PR_DIV_64 0x4
|
||||
#define IWDG_PR_DIV_128 0x5
|
||||
#define IWDG_PR_DIV_256 0x6
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define IWDG_SR_RVU_BIT 1
|
||||
#define IWDG_SR_PVU_BIT 0
|
||||
|
||||
#define IWDG_SR_RVU BIT(IWDG_SR_RVU_BIT)
|
||||
#define IWDG_SR_PVU BIT(IWDG_SR_PVU_BIT)
|
||||
|
||||
/**
|
||||
* @brief Independent watchdog prescalers.
|
||||
*
|
||||
* These divide the 40 kHz IWDG clock.
|
||||
*/
|
||||
typedef enum iwdg_prescaler {
|
||||
IWDG_PRE_4 = IWDG_PR_DIV_4, /**< Divide by 4 */
|
||||
IWDG_PRE_8 = IWDG_PR_DIV_8, /**< Divide by 8 */
|
||||
IWDG_PRE_16 = IWDG_PR_DIV_16, /**< Divide by 16 */
|
||||
IWDG_PRE_32 = IWDG_PR_DIV_32, /**< Divide by 32 */
|
||||
IWDG_PRE_64 = IWDG_PR_DIV_64, /**< Divide by 64 */
|
||||
IWDG_PRE_128 = IWDG_PR_DIV_128, /**< Divide by 128 */
|
||||
IWDG_PRE_256 = IWDG_PR_DIV_256 /**< Divide by 256 */
|
||||
} iwdg_prescaler;
|
||||
|
||||
void iwdg_init(iwdg_prescaler prescaler, uint16 reload);
|
||||
void iwdg_feed(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple.h
|
||||
* @brief General include file for libmaple
|
||||
*/
|
||||
|
||||
#ifndef _LIBMAPLE_H_
|
||||
#define _LIBMAPLE_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "stm32.h"
|
||||
#include "util.h"
|
||||
#include "delay.h"
|
||||
|
||||
/*
|
||||
* Where to put usercode, based on space reserved for bootloader.
|
||||
*
|
||||
* FIXME this has no business being here
|
||||
*/
|
||||
#if defined(MCU_STM32F103VE) || defined(MCU_STM32F205VE) || defined(MCU_STM32F406VG)
|
||||
/* e.g., Aeroquad32 */
|
||||
#define USER_ADDR_ROM 0x08010000 /* ala42 */
|
||||
#define USER_ADDR_RAM 0x20000C00
|
||||
#define STACK_TOP 0x20000800
|
||||
#elif defined(BOARD_freeflight)
|
||||
#define USER_ADDR_ROM 0x08000000
|
||||
#define USER_ADDR_RAM 0x20000000
|
||||
#define STACK_TOP 0x20000800
|
||||
#else
|
||||
#define USER_ADDR_ROM 0x08005000
|
||||
#define USER_ADDR_RAM 0x20000C00
|
||||
#define STACK_TOP 0x20000800
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple_types.h
|
||||
*
|
||||
* @brief libmaple types
|
||||
*/
|
||||
|
||||
#ifndef _LIBMAPLE_TYPES_H_
|
||||
#define _LIBMAPLE_TYPES_H_
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef short int16;
|
||||
typedef int int32;
|
||||
typedef long long int64;
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
|
||||
#define __io volatile
|
||||
#define __attr_flash __attribute__((section (".USER_FLASH")))
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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.
|
||||
*****************************************************************************/
|
||||
|
||||
extern void setup(void);
|
||||
extern void loop(void);
|
||||
extern void init(void);
|
||||
|
||||
// Force init to be called *first*, i.e. before static object allocation.
|
||||
// Otherwise, statically allocated objects that need libmaple may fail.
|
||||
__attribute__(( constructor )) void premain() {
|
||||
init();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
setup();
|
||||
|
||||
while (1) {
|
||||
loop();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file nvic.c
|
||||
* @brief Nested vector interrupt controller support.
|
||||
*/
|
||||
|
||||
#include "nvic.h"
|
||||
#include "scb.h"
|
||||
#include "stm32.h"
|
||||
|
||||
/**
|
||||
* @brief Set interrupt priority for an interrupt line
|
||||
*
|
||||
* Note: The STM32 only implements 4 bits of priority, ignoring the
|
||||
* lower 4 bits. This means there are only 16 levels of priority.
|
||||
* Bits[3:0] read as zero and ignore writes.
|
||||
*
|
||||
* @param irqn device to set
|
||||
* @param priority Priority to set, 0 being highest priority and 15
|
||||
* being lowest.
|
||||
*/
|
||||
void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority) {
|
||||
if (irqn < 0) {
|
||||
/* This interrupt is in the system handler block */
|
||||
SCB_BASE->SHP[((uint32)irqn & 0xF) - 4] = (priority & 0xF) << 4;
|
||||
} else {
|
||||
NVIC_BASE->IP[irqn] = (priority & 0xF) << 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the NVIC
|
||||
* @param vector_table_address Vector table base address.
|
||||
* @param offset Offset from vector_table_address. Some restrictions
|
||||
* apply to the use of nonzero offsets; see ST RM0008
|
||||
* and the ARM Cortex M3 Technical Reference Manual.
|
||||
*/
|
||||
void nvic_init(uint32 vector_table_address, uint32 offset) {
|
||||
uint32 i;
|
||||
|
||||
nvic_set_vector_table(vector_table_address, offset);
|
||||
|
||||
/*
|
||||
* Lower priority level for all peripheral interrupts to lowest
|
||||
* possible.
|
||||
*/
|
||||
for (i = 0; i < STM32_NR_INTERRUPTS; i++) {
|
||||
nvic_irq_set_priority((nvic_irq_num)i, 0xF);
|
||||
}
|
||||
|
||||
/* Lower systick interrupt priority to lowest level */
|
||||
nvic_irq_set_priority(NVIC_SYSTICK, 0xF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the vector table address.
|
||||
*/
|
||||
void nvic_set_vector_table(uint32 addr, uint32 offset) {
|
||||
SCB_BASE->VTOR = addr | (offset & 0x1FFFFF80);
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file nvic.h
|
||||
* @brief Nested vector interrupt controller support.
|
||||
*
|
||||
* Basic usage:
|
||||
*
|
||||
* @code
|
||||
* // Initialise the interrupt controller and point to the vector
|
||||
* // table at the start of flash.
|
||||
* nvic_init(0x08000000, 0);
|
||||
* // Bind in a timer interrupt handler
|
||||
* timer_attach_interrupt(TIMER_CC1_INTERRUPT, handler);
|
||||
* // Optionally set the priority
|
||||
* nvic_irq_set_priority(NVIC_TIMER1_CC, 5);
|
||||
* // All done, enable all interrupts
|
||||
* nvic_globalirq_enable();
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
#ifndef _NVIC_H_
|
||||
#define _NVIC_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** NVIC register map type. */
|
||||
typedef struct nvic_reg_map {
|
||||
__io uint32 ISER[8]; /**< Interrupt Set Enable Registers */
|
||||
uint32 RESERVED0[24]; /**< Reserved */
|
||||
__io uint32 ICER[8]; /**< Interrupt Clear Enable Registers */
|
||||
uint32 RSERVED1[24]; /**< Reserved */
|
||||
__io uint32 ISPR[8]; /**< Interrupt Set Pending Registers */
|
||||
uint32 RESERVED2[24]; /**< Reserved */
|
||||
__io uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */
|
||||
uint32 RESERVED3[24]; /**< Reserved */
|
||||
__io uint32 IABR[8]; /**< Interrupt Active bit Registers */
|
||||
uint32 RESERVED4[56]; /**< Reserved */
|
||||
__io uint8 IP[240]; /**< Interrupt Priority Registers */
|
||||
uint32 RESERVED5[644]; /**< Reserved */
|
||||
__io uint32 STIR; /**< Software Trigger Interrupt Registers */
|
||||
} nvic_reg_map;
|
||||
|
||||
/** NVIC register map base pointer. */
|
||||
#define NVIC_BASE ((struct nvic_reg_map*)0xE000E100)
|
||||
|
||||
/**
|
||||
* @brief Interrupt vector table interrupt numbers.
|
||||
*
|
||||
* Each positive-valued enumerator is the position of the
|
||||
* corresponding interrupt in the vector table. Negative-valued
|
||||
* enumerators correspond to interrupts controlled by the system
|
||||
* handler block.
|
||||
*
|
||||
* @see scb.h
|
||||
*/
|
||||
typedef enum nvic_irq_num {
|
||||
NVIC_NMI = -14, /**< Non-maskable interrupt */
|
||||
NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */
|
||||
NVIC_MEM_MANAGE = -12, /**< Memory management */
|
||||
NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory
|
||||
access fault. */
|
||||
NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction or
|
||||
illegal state. */
|
||||
NVIC_SVC = -5, /**< System service call via SWI insruction */
|
||||
NVIC_DEBUG_MON = -4, /**< Debug monitor */
|
||||
NVIC_PEND_SVC = -2, /**< Pendable request for system service */
|
||||
NVIC_SYSTICK = -1, /**< System tick timer */
|
||||
NVIC_WWDG = 0, /**< Window watchdog interrupt */
|
||||
NVIC_PVD = 1, /**< PVD through EXTI line detection */
|
||||
NVIC_TAMPER = 2, /**< Tamper */
|
||||
NVIC_RTC = 3, /**< Real-time clock */
|
||||
NVIC_FLASH = 4, /**< Flash */
|
||||
NVIC_RCC = 5, /**< Reset and clock control */
|
||||
NVIC_EXTI0 = 6, /**< EXTI line 0 */
|
||||
NVIC_EXTI1 = 7, /**< EXTI line 1 */
|
||||
NVIC_EXTI2 = 8, /**< EXTI line 2 */
|
||||
NVIC_EXTI3 = 9, /**< EXTI line 3 */
|
||||
NVIC_EXTI4 = 10, /**< EXTI line 4 */
|
||||
NVIC_DMA_CH1 = 11, /**< DMA1 channel 1 */
|
||||
NVIC_DMA_CH2 = 12, /**< DMA1 channel 2 */
|
||||
NVIC_DMA_CH3 = 13, /**< DMA1 channel 3 */
|
||||
NVIC_DMA_CH4 = 14, /**< DMA1 channel 4 */
|
||||
NVIC_DMA_CH5 = 15, /**< DMA1 channel 5 */
|
||||
NVIC_DMA_CH6 = 16, /**< DMA1 channel 6 */
|
||||
NVIC_DMA_CH7 = 17, /**< DMA1 channel 7 */
|
||||
NVIC_ADC_1_2 = 18, /**< ADC1 and ADC2 */
|
||||
NVIC_USB_HP_CAN_TX = 19, /**< USB high priority or CAN TX */
|
||||
NVIC_USB_LP_CAN_RX0 = 20, /**< USB low priority or CAN RX0 */
|
||||
NVIC_CAN_RX1 = 21, /**< CAN RX1 */
|
||||
NVIC_CAN_SCE = 22, /**< CAN SCE */
|
||||
NVIC_EXTI_9_5 = 23, /**< EXTI line [9:5] */
|
||||
NVIC_TIMER1_BRK = 24, /**< Timer 1 break */
|
||||
NVIC_TIMER1_UP = 25, /**< Timer 1 update */
|
||||
NVIC_TIMER1_TRG_COM = 26, /**< Timer 1 trigger and commutation */
|
||||
NVIC_TIMER1_CC = 27, /**< Timer 1 capture/compare */
|
||||
NVIC_TIMER2 = 28, /**< Timer 2 */
|
||||
NVIC_TIMER3 = 29, /**< Timer 3 */
|
||||
NVIC_TIMER4 = 30, /**< Timer 4 */
|
||||
NVIC_I2C1_EV = 31, /**< I2C1 event */
|
||||
NVIC_I2C1_ER = 32, /**< I2C1 error */
|
||||
NVIC_I2C2_EV = 33, /**< I2C2 event */
|
||||
NVIC_I2C2_ER = 34, /**< I2C2 error */
|
||||
NVIC_SPI1 = 35, /**< SPI1 */
|
||||
NVIC_SPI2 = 36, /**< SPI2 */
|
||||
NVIC_USART1 = 37, /**< USART1 */
|
||||
NVIC_USART2 = 38, /**< USART2 */
|
||||
NVIC_USART3 = 39, /**< USART3 */
|
||||
NVIC_EXTI_15_10 = 40, /**< EXTI line [15:10] */
|
||||
NVIC_RTCALARM = 41, /**< RTC alarm through EXTI line */
|
||||
NVIC_USBWAKEUP = 42, /**< USB wakeup from suspend through
|
||||
EXTI line */
|
||||
NVIC_TIMER8_BRK = 43, /**< Timer 8 break */
|
||||
NVIC_TIMER8_UP = 44, /**< Timer 8 update */
|
||||
NVIC_TIMER8_TRG_COM = 45, /**< Timer 8 trigger and commutation */
|
||||
NVIC_TIMER8_CC = 46, /**< Timer 8 capture/compare */
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
NVIC_ADC3 = 47, /**< ADC3 */
|
||||
NVIC_FSMC = 48, /**< FSMC */
|
||||
NVIC_SDIO = 49, /**< SDIO */
|
||||
NVIC_TIMER5 = 50, /**< Timer 5 */
|
||||
NVIC_SPI3 = 51, /**< SPI3 */
|
||||
NVIC_UART4 = 52, /**< UART4 */
|
||||
NVIC_UART5 = 53, /**< UART5 */
|
||||
NVIC_TIMER6 = 54, /**< Timer 6 */
|
||||
NVIC_TIMER7 = 55, /**< Timer 7 */
|
||||
NVIC_DMA2_CH1 = 56, /**< DMA2 channel 1 */
|
||||
NVIC_DMA2_CH2 = 57, /**< DMA2 channel 2 */
|
||||
NVIC_DMA2_CH3 = 58, /**< DMA2 channel 3 */
|
||||
NVIC_DMA2_CH_4_5 = 59, /**< DMA2 channels 4 and 5 */
|
||||
#endif
|
||||
} nvic_irq_num;
|
||||
|
||||
/*
|
||||
* Initialises the interrupt controller and sets all interrupts to the
|
||||
* lowest priority.
|
||||
*
|
||||
* For stand-alone products, the base address is normally the start of
|
||||
* flash (0x08000000).
|
||||
*
|
||||
* @param vector_table_address base address of the vector table
|
||||
*/
|
||||
void nvic_init(uint32 vector_table_address, uint32 offset);
|
||||
|
||||
/**
|
||||
* Sets the base address of the vector table.
|
||||
*/
|
||||
void nvic_set_vector_table(uint32 address, uint32 offset);
|
||||
|
||||
void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority);
|
||||
|
||||
/**
|
||||
* Enables interrupts and configurable fault handlers (clear PRIMASK).
|
||||
*/
|
||||
static inline void nvic_globalirq_enable() {
|
||||
asm volatile("cpsie i");
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable interrupts and configurable fault handlers (set PRIMASK).
|
||||
*/
|
||||
static inline void nvic_globalirq_disable() {
|
||||
asm volatile("cpsid i");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt irq_num
|
||||
* @param irq_num Interrupt to enable
|
||||
*/
|
||||
static inline void nvic_irq_enable(nvic_irq_num irq_num) {
|
||||
if (irq_num < 0) {
|
||||
return;
|
||||
}
|
||||
NVIC_BASE->ISER[irq_num / 32] = BIT(irq_num % 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt irq_num
|
||||
* @param irq_num Interrupt to disable
|
||||
*/
|
||||
static inline void nvic_irq_disable(nvic_irq_num irq_num) {
|
||||
if (irq_num < 0) {
|
||||
return;
|
||||
}
|
||||
NVIC_BASE->ICER[irq_num / 32] = BIT(irq_num % 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Quickly disable all interrupts.
|
||||
*
|
||||
* Calling this function is significantly faster than calling
|
||||
* nvic_irq_disable() in a loop.
|
||||
*/
|
||||
static inline void nvic_irq_disable_all(void) {
|
||||
/* Note: This only works up to XL density. The fix for
|
||||
* connectivity line is:
|
||||
*
|
||||
* NVIC_BASE->ICER[2] = 0xF;
|
||||
*
|
||||
* We don't support connectivity line devices (yet), so leave it
|
||||
* alone for now.
|
||||
*/
|
||||
NVIC_BASE->ICER[0] = 0xFFFFFFFF;
|
||||
NVIC_BASE->ICER[1] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/******************************************************************************
|
||||
* 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 pwr.c
|
||||
* @brief Power control (PWR) support.
|
||||
*/
|
||||
|
||||
#include "pwr.h"
|
||||
#include "rcc.h"
|
||||
|
||||
/**
|
||||
* Enables the power interface clock, and resets the power device.
|
||||
*/
|
||||
void pwr_init(void) {
|
||||
rcc_clk_enable(RCC_PWR);
|
||||
rcc_reset_dev(RCC_PWR);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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 pwr.h
|
||||
* @brief Power control (PWR) defines.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Power interface register map. */
|
||||
typedef struct pwr_reg_map {
|
||||
__io uint32 CR; /**< Control register */
|
||||
__io uint32 CSR; /**< Control and status register */
|
||||
} pwr_reg_map;
|
||||
|
||||
/** Power peripheral register map base pointer. */
|
||||
#define PWR_BASE ((struct pwr_reg_map*)0x40007000)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Control register */
|
||||
|
||||
/** Disable backup domain write protection bit */
|
||||
#define PWR_CR_DBP 8
|
||||
/** Power voltage detector enable bit */
|
||||
#define PWR_CR_PVDE 4
|
||||
/** Clear standby flag bit */
|
||||
#define PWR_CR_CSBF 3
|
||||
/** Clear wakeup flag bit */
|
||||
#define PWR_CR_CWUF 2
|
||||
/** Power down deepsleep bit */
|
||||
#define PWR_CR_PDDS 1
|
||||
/** Low-power deepsleep bit */
|
||||
#define PWR_CR_LPDS 0
|
||||
|
||||
/* Control and status register */
|
||||
|
||||
/** Enable wakeup pin bit */
|
||||
#define PWR_CSR_EWUP 8
|
||||
/** PVD output bit */
|
||||
#define PWR_CSR_PVDO 2
|
||||
/** Standby flag bit */
|
||||
#define PWR_CSR_SBF 1
|
||||
/** Wakeup flag bit */
|
||||
#define PWR_CSR_WUF 0
|
||||
|
||||
/*
|
||||
* Convenience functions
|
||||
*/
|
||||
|
||||
void pwr_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file rcc.c
|
||||
* @brief Implements pretty much only the basic clock setup on the
|
||||
* stm32, clock enable/disable and peripheral reset commands.
|
||||
*/
|
||||
|
||||
// #ifdef STM32F2
|
||||
// #include "rccF2.c"
|
||||
// #else
|
||||
// #include "rccF1.c"
|
||||
// #endif
|
|
@ -0,0 +1,36 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file rcc.h
|
||||
* @brief reset and clock control definitions and prototypes
|
||||
*/
|
||||
|
||||
#ifdef STM32F2
|
||||
#include "rccF2.h"
|
||||
#else
|
||||
#include "rccF1.h"
|
||||
#endif
|
|
@ -0,0 +1,233 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef STM32F1
|
||||
|
||||
/**
|
||||
* @file rcc.c
|
||||
* @brief Implements pretty much only the basic clock setup on the
|
||||
* stm32, clock enable/disable and peripheral reset commands.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "flash.h"
|
||||
#include "rcc.h"
|
||||
#include "bitband.h"
|
||||
|
||||
#define APB1 RCC_APB1
|
||||
#define APB2 RCC_APB2
|
||||
#define AHB RCC_AHB
|
||||
|
||||
struct rcc_dev_info {
|
||||
const rcc_clk_domain clk_domain;
|
||||
const uint8 line_num;
|
||||
};
|
||||
|
||||
/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset
|
||||
* register bit numbers. */
|
||||
static const struct rcc_dev_info rcc_dev_table[] = {
|
||||
[RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 },
|
||||
[RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 },
|
||||
[RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 },
|
||||
[RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 },
|
||||
[RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 },
|
||||
[RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 },
|
||||
[RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 },
|
||||
[RCC_ADC3] = { .clk_domain = APB2, .line_num = 15 },
|
||||
[RCC_USART1] = { .clk_domain = APB2, .line_num = 14 },
|
||||
[RCC_USART2] = { .clk_domain = APB1, .line_num = 17 },
|
||||
[RCC_USART3] = { .clk_domain = APB1, .line_num = 18 },
|
||||
[RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 },
|
||||
[RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 },
|
||||
[RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 },
|
||||
[RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 },
|
||||
[RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 },
|
||||
[RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 },
|
||||
[RCC_DMA1] = { .clk_domain = AHB, .line_num = 0 },
|
||||
[RCC_PWR] = { .clk_domain = APB1, .line_num = 28},
|
||||
[RCC_BKP] = { .clk_domain = APB1, .line_num = 27},
|
||||
[RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 },
|
||||
[RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 },
|
||||
[RCC_CRC] = { .clk_domain = AHB, .line_num = 6},
|
||||
[RCC_FLITF] = { .clk_domain = AHB, .line_num = 4},
|
||||
[RCC_SRAM] = { .clk_domain = AHB, .line_num = 2},
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
[RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 },
|
||||
[RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 },
|
||||
[RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 },
|
||||
[RCC_UART4] = { .clk_domain = APB1, .line_num = 19 },
|
||||
[RCC_UART5] = { .clk_domain = APB1, .line_num = 20 },
|
||||
[RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 },
|
||||
[RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 },
|
||||
[RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 },
|
||||
[RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 },
|
||||
[RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 },
|
||||
[RCC_DAC] = { .clk_domain = APB1, .line_num = 29 },
|
||||
[RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 },
|
||||
[RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 },
|
||||
[RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 },
|
||||
#endif
|
||||
#ifdef STM32_XL_DENSITY
|
||||
[RCC_TIMER9] = { .clk_domain = APB2, .line_num = 19 },
|
||||
[RCC_TIMER10] = { .clk_domain = APB2, .line_num = 20 },
|
||||
[RCC_TIMER11] = { .clk_domain = APB2, .line_num = 21 },
|
||||
[RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 },
|
||||
[RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 },
|
||||
[RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 },
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize the clock control system. Initializes the system
|
||||
* clock source to use the PLL driven by an external oscillator
|
||||
* @param sysclk_src system clock source, must be PLL
|
||||
* @param pll_src pll clock source, must be HSE
|
||||
* @param pll_mul pll multiplier
|
||||
*/
|
||||
void rcc_clk_init(rcc_sysclk_src sysclk_src,
|
||||
rcc_pllsrc pll_src,
|
||||
rcc_pll_multiplier pll_mul) {
|
||||
uint32 cfgr = 0;
|
||||
uint32 cr;
|
||||
|
||||
/* Assume that we're going to clock the chip off the PLL, fed by
|
||||
* the HSE */
|
||||
ASSERT(sysclk_src == RCC_CLKSRC_PLL &&
|
||||
pll_src == RCC_PLLSRC_HSE);
|
||||
|
||||
RCC_BASE->CFGR = pll_src | pll_mul;
|
||||
|
||||
/* Turn on the HSE */
|
||||
cr = RCC_BASE->CR;
|
||||
cr |= RCC_CR_HSEON;
|
||||
RCC_BASE->CR = cr;
|
||||
while (!(RCC_BASE->CR & RCC_CR_HSERDY))
|
||||
;
|
||||
|
||||
/* Now the PLL */
|
||||
cr |= RCC_CR_PLLON;
|
||||
RCC_BASE->CR = cr;
|
||||
while (!(RCC_BASE->CR & RCC_CR_PLLRDY))
|
||||
;
|
||||
|
||||
/* Finally, let's switch over to the PLL */
|
||||
cfgr &= ~RCC_CFGR_SW;
|
||||
cfgr |= RCC_CFGR_SW_PLL;
|
||||
RCC_BASE->CFGR = cfgr;
|
||||
while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn on the clock line on a peripheral
|
||||
* @param id Clock ID of the peripheral to turn on.
|
||||
*/
|
||||
void rcc_clk_enable(rcc_clk_id id) {
|
||||
static const __io uint32* enable_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1ENR,
|
||||
[APB2] = &RCC_BASE->APB2ENR,
|
||||
[AHB] = &RCC_BASE->AHBENR,
|
||||
};
|
||||
|
||||
rcc_clk_domain clk_domain = rcc_dev_clk(id);
|
||||
__io uint32* enr = (__io uint32*)enable_regs[clk_domain];
|
||||
uint8 lnum = rcc_dev_table[id].line_num;
|
||||
|
||||
bb_peri_set_bit(enr, lnum, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset a peripheral.
|
||||
* @param id Clock ID of the peripheral to reset.
|
||||
*/
|
||||
void rcc_reset_dev(rcc_clk_id id) {
|
||||
static const __io uint32* reset_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1RSTR,
|
||||
[APB2] = &RCC_BASE->APB2RSTR,
|
||||
};
|
||||
|
||||
rcc_clk_domain clk_domain = rcc_dev_clk(id);
|
||||
__io void* addr = (__io void*)reset_regs[clk_domain];
|
||||
uint8 lnum = rcc_dev_table[id].line_num;
|
||||
|
||||
bb_peri_set_bit(addr, lnum, 1);
|
||||
bb_peri_set_bit(addr, lnum, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's clock domain
|
||||
* @param id Clock ID of the peripheral whose clock domain to return
|
||||
* @return Clock source for the given clock ID
|
||||
*/
|
||||
rcc_clk_domain rcc_dev_clk(rcc_clk_id id) {
|
||||
return rcc_dev_table[id].clk_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's clock domain speed
|
||||
* @param id Clock ID of the peripheral whose clock domain speed to return
|
||||
* @return Clock speed for the given clock ID
|
||||
*/
|
||||
uint32 rcc_dev_clk_speed(rcc_clk_id id) {
|
||||
static const uint32 rcc_dev_clk_speed_table[] = {
|
||||
[RCC_AHB] = 72000000,
|
||||
[RCC_APB1] = 36000000,
|
||||
[RCC_APB2] = 72000000
|
||||
};
|
||||
return rcc_dev_clk_speed_table[rcc_dev_clk(id)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's timer clock domain speed
|
||||
* @param id Clock ID of the peripheral whose clock domain speed to return
|
||||
* @return Clock speed for the given clock ID
|
||||
*/
|
||||
uint32 rcc_dev_timer_clk_speed(rcc_clk_id id) {
|
||||
return rcc_dev_clk_speed(RCC_APB2); // 72 MHz for all counter
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the divider on a peripheral prescaler
|
||||
* @param prescaler prescaler to set
|
||||
* @param divider prescaler divider
|
||||
*/
|
||||
void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) {
|
||||
static const uint32 masks[] = {
|
||||
[RCC_PRESCALER_AHB] = RCC_CFGR_HPRE,
|
||||
[RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1,
|
||||
[RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2,
|
||||
[RCC_PRESCALER_USB] = RCC_CFGR_USBPRE,
|
||||
[RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE,
|
||||
};
|
||||
|
||||
uint32 cfgr = RCC_BASE->CFGR;
|
||||
cfgr &= ~masks[prescaler];
|
||||
cfgr |= divider;
|
||||
RCC_BASE->CFGR = cfgr;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,572 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file rcc.h
|
||||
* @brief reset and clock control definitions and prototypes
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
#ifndef _RCC_H_
|
||||
#define _RCC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** RCC register map type */
|
||||
typedef struct rcc_reg_map {
|
||||
__io uint32 CR; /**< Clock control register */
|
||||
__io uint32 CFGR; /**< Clock configuration register */
|
||||
__io uint32 CIR; /**< Clock interrupt register */
|
||||
__io uint32 APB2RSTR; /**< APB2 peripheral reset register */
|
||||
__io uint32 APB1RSTR; /**< APB1 peripheral reset register */
|
||||
__io uint32 AHBENR; /**< AHB peripheral clock enable register */
|
||||
__io uint32 APB2ENR; /**< APB2 peripheral clock enable register */
|
||||
__io uint32 APB1ENR; /**< APB1 peripheral clock enable register */
|
||||
__io uint32 BDCR; /**< Backup domain control register */
|
||||
__io uint32 CSR; /**< Control/status register */
|
||||
} rcc_reg_map;
|
||||
|
||||
/** RCC register map base pointer */
|
||||
#define RCC_BASE ((struct rcc_reg_map*)0x40021000)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Clock control register */
|
||||
|
||||
#define RCC_CR_PLLRDY_BIT 25
|
||||
#define RCC_CR_PLLON_BIT 24
|
||||
#define RCC_CR_CSSON_BIT 19
|
||||
#define RCC_CR_HSEBYP_BIT 18
|
||||
#define RCC_CR_HSERDY_BIT 17
|
||||
#define RCC_CR_HSEON_BIT 16
|
||||
#define RCC_CR_HSIRDY_BIT 1
|
||||
#define RCC_CR_HSION_BIT 0
|
||||
|
||||
#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT)
|
||||
#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT)
|
||||
#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT)
|
||||
#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT)
|
||||
#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT)
|
||||
#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT)
|
||||
#define RCC_CR_HSICAL (0xFF << 8)
|
||||
#define RCC_CR_HSITRIM (0x1F << 3)
|
||||
#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT)
|
||||
#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT)
|
||||
|
||||
/* Clock configuration register */
|
||||
|
||||
#define RCC_CFGR_USBPRE_BIT 22
|
||||
#define RCC_CFGR_PLLXTPRE_BIT 17
|
||||
#define RCC_CFGR_PLLSRC_BIT 16
|
||||
|
||||
#define RCC_CFGR_MCO (0x3 << 24)
|
||||
#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT)
|
||||
#define RCC_CFGR_PLLMUL (0xF << 18)
|
||||
#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT)
|
||||
#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT)
|
||||
#define RCC_CFGR_ADCPRE (0x3 << 14)
|
||||
#define RCC_CFGR_PPRE2 (0x7 << 11)
|
||||
#define RCC_CFGR_PPRE1 (0x7 << 8)
|
||||
#define RCC_CFGR_HPRE (0xF << 4)
|
||||
#define RCC_CFGR_SWS (0x3 << 2)
|
||||
#define RCC_CFGR_SWS_PLL (0x2 << 2)
|
||||
#define RCC_CFGR_SWS_HSE (0x1 << 2)
|
||||
#define RCC_CFGR_SW 0x3
|
||||
#define RCC_CFGR_SW_PLL 0x2
|
||||
#define RCC_CFGR_SW_HSE 0x1
|
||||
|
||||
/* Clock interrupt register */
|
||||
|
||||
#define RCC_CIR_CSSC_BIT 23
|
||||
#define RCC_CIR_PLLRDYC_BIT 20
|
||||
#define RCC_CIR_HSERDYC_BIT 19
|
||||
#define RCC_CIR_HSIRDYC_BIT 18
|
||||
#define RCC_CIR_LSERDYC_BIT 17
|
||||
#define RCC_CIR_LSIRDYC_BIT 16
|
||||
#define RCC_CIR_PLLRDYIE_BIT 12
|
||||
#define RCC_CIR_HSERDYIE_BIT 11
|
||||
#define RCC_CIR_HSIRDYIE_BIT 10
|
||||
#define RCC_CIR_LSERDYIE_BIT 9
|
||||
#define RCC_CIR_LSIRDYIE_BIT 8
|
||||
#define RCC_CIR_CSSF_BIT 7
|
||||
#define RCC_CIR_PLLRDYF_BIT 4
|
||||
#define RCC_CIR_HSERDYF_BIT 3
|
||||
#define RCC_CIR_HSIRDYF_BIT 2
|
||||
#define RCC_CIR_LSERDYF_BIT 1
|
||||
#define RCC_CIR_LSIRDYF_BIT 0
|
||||
|
||||
#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT)
|
||||
#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT)
|
||||
#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT)
|
||||
#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT)
|
||||
#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT)
|
||||
#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT)
|
||||
#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT)
|
||||
#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT)
|
||||
#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT)
|
||||
#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT)
|
||||
#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT)
|
||||
#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT)
|
||||
#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT)
|
||||
#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT)
|
||||
#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT)
|
||||
#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT)
|
||||
#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT)
|
||||
|
||||
/* APB2 peripheral reset register */
|
||||
|
||||
#define RCC_APB2RSTR_TIM11RST_BIT 21
|
||||
#define RCC_APB2RSTR_TIM10RST_BIT 20
|
||||
#define RCC_APB2RSTR_TIM9RST_BIT 19
|
||||
#define RCC_APB2RSTR_ADC3RST_BIT 15
|
||||
#define RCC_APB2RSTR_USART1RST_BIT 14
|
||||
#define RCC_APB2RSTR_TIM8RST_BIT 13
|
||||
#define RCC_APB2RSTR_SPI1RST_BIT 12
|
||||
#define RCC_APB2RSTR_TIM1RST_BIT 11
|
||||
#define RCC_APB2RSTR_ADC2RST_BIT 10
|
||||
#define RCC_APB2RSTR_ADC1RST_BIT 9
|
||||
#define RCC_APB2RSTR_IOPGRST_BIT 8
|
||||
#define RCC_APB2RSTR_IOPFRST_BIT 7
|
||||
#define RCC_APB2RSTR_IOPERST_BIT 6
|
||||
#define RCC_APB2RSTR_IOPDRST_BIT 5
|
||||
#define RCC_APB2RSTR_IOPCRST_BIT 4
|
||||
#define RCC_APB2RSTR_IOPBRST_BIT 3
|
||||
#define RCC_APB2RSTR_IOPARST_BIT 2
|
||||
#define RCC_APB2RSTR_AFIORST_BIT 0
|
||||
|
||||
#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT)
|
||||
#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT)
|
||||
#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT)
|
||||
#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT)
|
||||
#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT)
|
||||
#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT)
|
||||
#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT)
|
||||
#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT)
|
||||
#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT)
|
||||
|
||||
/* APB1 peripheral reset register */
|
||||
|
||||
#define RCC_APB1RSTR_DACRST_BIT 29
|
||||
#define RCC_APB1RSTR_PWRRST_BIT 28
|
||||
#define RCC_APB1RSTR_BKPRST_BIT 27
|
||||
#define RCC_APB1RSTR_CANRST_BIT 25
|
||||
#define RCC_APB1RSTR_USBRST_BIT 23
|
||||
#define RCC_APB1RSTR_I2C2RST_BIT 22
|
||||
#define RCC_APB1RSTR_I2C1RST_BIT 21
|
||||
#define RCC_APB1RSTR_UART5RST_BIT 20
|
||||
#define RCC_APB1RSTR_UART4RST_BIT 19
|
||||
#define RCC_APB1RSTR_USART3RST_BIT 18
|
||||
#define RCC_APB1RSTR_USART2RST_BIT 17
|
||||
#define RCC_APB1RSTR_SPI3RST_BIT 15
|
||||
#define RCC_APB1RSTR_SPI2RST_BIT 14
|
||||
#define RCC_APB1RSTR_WWDRST_BIT 11
|
||||
#define RCC_APB1RSTR_TIM14RST_BIT 8
|
||||
#define RCC_APB1RSTR_TIM13RST_BIT 7
|
||||
#define RCC_APB1RSTR_TIM12RST_BIT 6
|
||||
#define RCC_APB1RSTR_TIM7RST_BIT 5
|
||||
#define RCC_APB1RSTR_TIM6RST_BIT 4
|
||||
#define RCC_APB1RSTR_TIM5RST_BIT 3
|
||||
#define RCC_APB1RSTR_TIM4RST_BIT 2
|
||||
#define RCC_APB1RSTR_TIM3RST_BIT 1
|
||||
#define RCC_APB1RSTR_TIM2RST_BIT 0
|
||||
|
||||
#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT)
|
||||
#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT)
|
||||
#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT)
|
||||
#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT)
|
||||
#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT)
|
||||
#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT)
|
||||
#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT)
|
||||
#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT)
|
||||
#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT)
|
||||
#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT)
|
||||
#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT)
|
||||
#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT)
|
||||
#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT)
|
||||
#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT)
|
||||
#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT)
|
||||
|
||||
/* AHB peripheral clock enable register */
|
||||
|
||||
#define RCC_AHBENR_SDIOEN_BIT 10
|
||||
#define RCC_AHBENR_FSMCEN_BIT 8
|
||||
#define RCC_AHBENR_CRCEN_BIT 7
|
||||
#define RCC_AHBENR_FLITFEN_BIT 4
|
||||
#define RCC_AHBENR_SRAMEN_BIT 2
|
||||
#define RCC_AHBENR_DMA2EN_BIT 1
|
||||
#define RCC_AHBENR_DMA1EN_BIT 0
|
||||
|
||||
#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT)
|
||||
#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT)
|
||||
#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT)
|
||||
#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT)
|
||||
#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT)
|
||||
#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT)
|
||||
#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT)
|
||||
|
||||
/* APB2 peripheral clock enable register */
|
||||
|
||||
#define RCC_APB2ENR_TIM11EN_BIT 21
|
||||
#define RCC_APB2ENR_TIM10EN_BIT 20
|
||||
#define RCC_APB2ENR_TIM9EN_BIT 19
|
||||
#define RCC_APB2ENR_ADC3EN_BIT 15
|
||||
#define RCC_APB2ENR_USART1EN_BIT 14
|
||||
#define RCC_APB2ENR_TIM8EN_BIT 13
|
||||
#define RCC_APB2ENR_SPI1EN_BIT 12
|
||||
#define RCC_APB2ENR_TIM1EN_BIT 11
|
||||
#define RCC_APB2ENR_ADC2EN_BIT 10
|
||||
#define RCC_APB2ENR_ADC1EN_BIT 9
|
||||
#define RCC_APB2ENR_IOPGEN_BIT 8
|
||||
#define RCC_APB2ENR_IOPFEN_BIT 7
|
||||
#define RCC_APB2ENR_IOPEEN_BIT 6
|
||||
#define RCC_APB2ENR_IOPDEN_BIT 5
|
||||
#define RCC_APB2ENR_IOPCEN_BIT 4
|
||||
#define RCC_APB2ENR_IOPBEN_BIT 3
|
||||
#define RCC_APB2ENR_IOPAEN_BIT 2
|
||||
#define RCC_APB2ENR_AFIOEN_BIT 0
|
||||
|
||||
#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT)
|
||||
#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT)
|
||||
#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT)
|
||||
#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT)
|
||||
#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT)
|
||||
#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT)
|
||||
#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT)
|
||||
#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT)
|
||||
#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT)
|
||||
#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT)
|
||||
#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT)
|
||||
#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT)
|
||||
#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT)
|
||||
#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT)
|
||||
#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT)
|
||||
#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT)
|
||||
#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT)
|
||||
#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT)
|
||||
|
||||
/* APB1 peripheral clock enable register */
|
||||
|
||||
#define RCC_APB1ENR_DACEN_BIT 29
|
||||
#define RCC_APB1ENR_PWREN_BIT 28
|
||||
#define RCC_APB1ENR_BKPEN_BIT 27
|
||||
#define RCC_APB1ENR_CANEN_BIT 25
|
||||
#define RCC_APB1ENR_USBEN_BIT 23
|
||||
#define RCC_APB1ENR_I2C2EN_BIT 22
|
||||
#define RCC_APB1ENR_I2C1EN_BIT 21
|
||||
#define RCC_APB1ENR_UART5EN_BIT 20
|
||||
#define RCC_APB1ENR_UART4EN_BIT 19
|
||||
#define RCC_APB1ENR_USART3EN_BIT 18
|
||||
#define RCC_APB1ENR_USART2EN_BIT 17
|
||||
#define RCC_APB1ENR_SPI3EN_BIT 15
|
||||
#define RCC_APB1ENR_SPI2EN_BIT 14
|
||||
#define RCC_APB1ENR_WWDEN_BIT 11
|
||||
#define RCC_APB1ENR_TIM14EN_BIT 8
|
||||
#define RCC_APB1ENR_TIM13EN_BIT 7
|
||||
#define RCC_APB1ENR_TIM12EN_BIT 6
|
||||
#define RCC_APB1ENR_TIM7EN_BIT 5
|
||||
#define RCC_APB1ENR_TIM6EN_BIT 4
|
||||
#define RCC_APB1ENR_TIM5EN_BIT 3
|
||||
#define RCC_APB1ENR_TIM4EN_BIT 2
|
||||
#define RCC_APB1ENR_TIM3EN_BIT 1
|
||||
#define RCC_APB1ENR_TIM2EN_BIT 0
|
||||
|
||||
#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT)
|
||||
#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT)
|
||||
#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT)
|
||||
#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT)
|
||||
#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT)
|
||||
#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT)
|
||||
#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT)
|
||||
#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT)
|
||||
#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT)
|
||||
#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT)
|
||||
#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT)
|
||||
#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT)
|
||||
#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT)
|
||||
#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT)
|
||||
#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT)
|
||||
#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT)
|
||||
#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT)
|
||||
#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT)
|
||||
#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT)
|
||||
#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT)
|
||||
#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT)
|
||||
#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT)
|
||||
#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT)
|
||||
|
||||
/* Backup domain control register */
|
||||
|
||||
#define RCC_BDCR_BDRST_BIT 16
|
||||
#define RCC_BDCR_RTCEN_BIT 15
|
||||
#define RCC_BDCR_LSEBYP_BIT 2
|
||||
#define RCC_BDCR_LSERDY_BIT 1
|
||||
#define RCC_BDCR_LSEON_BIT 0
|
||||
|
||||
#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT)
|
||||
#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT)
|
||||
#define RCC_BDCR_RTCSEL (0x3 << 8)
|
||||
#define RCC_BDCR_RTCSEL_NONE (0x0 << 8)
|
||||
#define RCC_BDCR_RTCSEL_LSE (0x1 << 8)
|
||||
#define RCC_BDCR_RTCSEL_HSE (0x3 << 8)
|
||||
#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT)
|
||||
#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT)
|
||||
#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT)
|
||||
|
||||
/* Control/status register */
|
||||
|
||||
#define RCC_CSR_LPWRRSTF_BIT 31
|
||||
#define RCC_CSR_WWDGRSTF_BIT 30
|
||||
#define RCC_CSR_IWDGRSTF_BIT 29
|
||||
#define RCC_CSR_SFTRSTF_BIT 28
|
||||
#define RCC_CSR_PORRSTF_BIT 27
|
||||
#define RCC_CSR_PINRSTF_BIT 26
|
||||
#define RCC_CSR_RMVF_BIT 24
|
||||
#define RCC_CSR_LSIRDY_BIT 1
|
||||
#define RCC_CSR_LSION_BIT 0
|
||||
|
||||
#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT)
|
||||
#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT)
|
||||
#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT)
|
||||
#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT)
|
||||
#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT)
|
||||
#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT)
|
||||
#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT)
|
||||
#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT)
|
||||
#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT)
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* SYSCLK sources
|
||||
* @see rcc_clk_init()
|
||||
*/
|
||||
typedef enum rcc_sysclk_src {
|
||||
RCC_CLKSRC_HSI = 0x0,
|
||||
RCC_CLKSRC_HSE = 0x1,
|
||||
RCC_CLKSRC_PLL = 0x2,
|
||||
} rcc_sysclk_src;
|
||||
|
||||
/**
|
||||
* PLL entry clock source
|
||||
* @see rcc_clk_init()
|
||||
*/
|
||||
typedef enum rcc_pllsrc {
|
||||
RCC_PLLSRC_HSE = (0x1 << 16),
|
||||
RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16)
|
||||
} rcc_pllsrc;
|
||||
|
||||
/**
|
||||
* PLL multipliers
|
||||
* @see rcc_clk_init()
|
||||
*/
|
||||
typedef enum rcc_pll_multiplier {
|
||||
RCC_PLLMUL_2 = (0x0 << 18),
|
||||
RCC_PLLMUL_3 = (0x1 << 18),
|
||||
RCC_PLLMUL_4 = (0x2 << 18),
|
||||
RCC_PLLMUL_5 = (0x3 << 18),
|
||||
RCC_PLLMUL_6 = (0x4 << 18),
|
||||
RCC_PLLMUL_7 = (0x5 << 18),
|
||||
RCC_PLLMUL_8 = (0x6 << 18),
|
||||
RCC_PLLMUL_9 = (0x7 << 18),
|
||||
RCC_PLLMUL_10 = (0x8 << 18),
|
||||
RCC_PLLMUL_11 = (0x9 << 18),
|
||||
RCC_PLLMUL_12 = (0xA << 18),
|
||||
RCC_PLLMUL_13 = (0xB << 18),
|
||||
RCC_PLLMUL_14 = (0xC << 18),
|
||||
RCC_PLLMUL_15 = (0xD << 18),
|
||||
RCC_PLLMUL_16 = (0xE << 18),
|
||||
} rcc_pll_multiplier;
|
||||
|
||||
/**
|
||||
* @brief Identifies bus and clock line for a peripheral.
|
||||
*
|
||||
* Also generally useful as a unique identifier for that peripheral
|
||||
* (or its corresponding device struct).
|
||||
*/
|
||||
typedef enum rcc_clk_id {
|
||||
RCC_GPIOA,
|
||||
RCC_GPIOB,
|
||||
RCC_GPIOC,
|
||||
RCC_GPIOD,
|
||||
RCC_AFIO,
|
||||
RCC_ADC1,
|
||||
RCC_ADC2,
|
||||
RCC_ADC3,
|
||||
RCC_USART1,
|
||||
RCC_USART2,
|
||||
RCC_USART3,
|
||||
RCC_TIMER1,
|
||||
RCC_TIMER2,
|
||||
RCC_TIMER3,
|
||||
RCC_TIMER4,
|
||||
RCC_SPI1,
|
||||
RCC_SPI2,
|
||||
RCC_DMA1,
|
||||
RCC_PWR,
|
||||
RCC_BKP,
|
||||
RCC_I2C1,
|
||||
RCC_I2C2,
|
||||
RCC_CRC,
|
||||
RCC_FLITF,
|
||||
RCC_SRAM,
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
RCC_GPIOE,
|
||||
RCC_GPIOF,
|
||||
RCC_GPIOG,
|
||||
RCC_UART4,
|
||||
RCC_UART5,
|
||||
RCC_TIMER5,
|
||||
RCC_TIMER6,
|
||||
RCC_TIMER7,
|
||||
RCC_TIMER8,
|
||||
RCC_FSMC,
|
||||
RCC_DAC,
|
||||
RCC_DMA2,
|
||||
RCC_SDIO,
|
||||
RCC_SPI3,
|
||||
#endif
|
||||
#ifdef STM32_XL_DENSITY
|
||||
RCC_TIMER9,
|
||||
RCC_TIMER10,
|
||||
RCC_TIMER11,
|
||||
RCC_TIMER12,
|
||||
RCC_TIMER13,
|
||||
RCC_TIMER14,
|
||||
#endif
|
||||
} rcc_clk_id;
|
||||
|
||||
void rcc_clk_init(rcc_sysclk_src sysclk_src,
|
||||
rcc_pllsrc pll_src,
|
||||
rcc_pll_multiplier pll_mul);
|
||||
void rcc_clk_enable(rcc_clk_id device);
|
||||
void rcc_reset_dev(rcc_clk_id device);
|
||||
|
||||
typedef enum rcc_clk_domain {
|
||||
RCC_APB1,
|
||||
RCC_APB2,
|
||||
RCC_AHB
|
||||
} rcc_clk_domain;
|
||||
|
||||
rcc_clk_domain rcc_dev_clk(rcc_clk_id device);
|
||||
|
||||
uint32 rcc_dev_clk_speed(rcc_clk_id id);
|
||||
uint32 rcc_dev_timer_clk_speed(rcc_clk_id id);
|
||||
|
||||
/**
|
||||
* Prescaler identifiers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_prescaler {
|
||||
RCC_PRESCALER_AHB,
|
||||
RCC_PRESCALER_APB1,
|
||||
RCC_PRESCALER_APB2,
|
||||
RCC_PRESCALER_USB,
|
||||
RCC_PRESCALER_ADC
|
||||
} rcc_prescaler;
|
||||
|
||||
/**
|
||||
* ADC prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_adc_divider {
|
||||
RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14,
|
||||
RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14,
|
||||
RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14,
|
||||
RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14,
|
||||
} rcc_adc_divider;
|
||||
|
||||
/**
|
||||
* APB1 prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_apb1_divider {
|
||||
RCC_APB1_HCLK_DIV_1 = 0x0 << 8,
|
||||
RCC_APB1_HCLK_DIV_2 = 0x4 << 8,
|
||||
RCC_APB1_HCLK_DIV_4 = 0x5 << 8,
|
||||
RCC_APB1_HCLK_DIV_8 = 0x6 << 8,
|
||||
RCC_APB1_HCLK_DIV_16 = 0x7 << 8,
|
||||
} rcc_apb1_divider;
|
||||
|
||||
/**
|
||||
* APB2 prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_apb2_divider {
|
||||
RCC_APB2_HCLK_DIV_1 = 0x0 << 11,
|
||||
RCC_APB2_HCLK_DIV_2 = 0x4 << 11,
|
||||
RCC_APB2_HCLK_DIV_4 = 0x5 << 11,
|
||||
RCC_APB2_HCLK_DIV_8 = 0x6 << 11,
|
||||
RCC_APB2_HCLK_DIV_16 = 0x7 << 11,
|
||||
} rcc_apb2_divider;
|
||||
|
||||
/**
|
||||
* AHB prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_ahb_divider {
|
||||
RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4,
|
||||
RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4,
|
||||
RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4,
|
||||
RCC_AHB_SYSCLK_DIV_8 = 0xA << 4,
|
||||
RCC_AHB_SYSCLK_DIV_16 = 0xB << 4,
|
||||
RCC_AHB_SYSCLK_DIV_32 = 0xC << 4,
|
||||
RCC_AHB_SYSCLK_DIV_64 = 0xD << 4,
|
||||
RCC_AHB_SYSCLK_DIV_128 = 0xD << 4,
|
||||
RCC_AHB_SYSCLK_DIV_256 = 0xE << 4,
|
||||
RCC_AHB_SYSCLK_DIV_512 = 0xF << 4,
|
||||
} rcc_ahb_divider;
|
||||
|
||||
void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,687 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef STM32F2
|
||||
|
||||
/**
|
||||
* @file rcc.c
|
||||
* @brief Implements pretty much only the basic clock setup on the
|
||||
* stm32, clock enable/disable and peripheral reset commands.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
#include "flash.h"
|
||||
#include "rcc.h"
|
||||
#include "bitband.h"
|
||||
|
||||
#define APB1 RCC_APB1
|
||||
#define APB2 RCC_APB2
|
||||
#define AHB1 RCC_AHB1
|
||||
#define AHB2 RCC_AHB2
|
||||
#define AHB3 RCC_AHB3
|
||||
|
||||
struct rcc_dev_info {
|
||||
const rcc_clk_domain clk_domain;
|
||||
const uint8 line_num;
|
||||
};
|
||||
|
||||
static uint32 rcc_dev_clk_speed_table[AHB3];
|
||||
|
||||
/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset
|
||||
* register bit numbers. */
|
||||
static const struct rcc_dev_info rcc_dev_table[] = {
|
||||
[RCC_GPIOA] = { .clk_domain = AHB1, .line_num = 0 }, //*
|
||||
[RCC_GPIOB] = { .clk_domain = AHB1, .line_num = 1 }, //*
|
||||
[RCC_GPIOC] = { .clk_domain = AHB1, .line_num = 2 }, //*
|
||||
[RCC_GPIOD] = { .clk_domain = AHB1, .line_num = 3 }, //*
|
||||
|
||||
// [RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 },
|
||||
[RCC_ADC1] = { .clk_domain = APB2, .line_num = 8 }, //*
|
||||
[RCC_ADC2] = { .clk_domain = APB2, .line_num = 9 }, //*
|
||||
[RCC_ADC3] = { .clk_domain = APB2, .line_num = 10 }, //*
|
||||
[RCC_USART1] = { .clk_domain = APB2, .line_num = 4 }, //*
|
||||
[RCC_USART2] = { .clk_domain = APB1, .line_num = 17 }, //unchanged
|
||||
[RCC_USART3] = { .clk_domain = APB1, .line_num = 18 }, //unchanged
|
||||
[RCC_TIMER1] = { .clk_domain = APB2, .line_num = 0 }, //*
|
||||
[RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 }, //unchanged
|
||||
[RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 }, //unchanged
|
||||
[RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 }, //unchanged
|
||||
[RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 }, //unchanged
|
||||
[RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 }, //unchanged
|
||||
[RCC_DMA1] = { .clk_domain = AHB1, .line_num = 21 }, //*
|
||||
[RCC_PWR] = { .clk_domain = APB1, .line_num = 28}, //unchanged
|
||||
// [RCC_BKP] = { .clk_domain = AHB1, .line_num = 18}, //*
|
||||
[RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 }, //unchanged
|
||||
[RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 }, //unchanged
|
||||
[RCC_CRC] = { .clk_domain = AHB1, .line_num = 12}, //*
|
||||
// [RCC_FLITF] = { .clk_domain = AHB, .line_num = 4},
|
||||
// [RCC_SRAM] = { .clk_domain = AHB, .line_num = 2},
|
||||
|
||||
[RCC_GPIOE] = { .clk_domain = AHB1, .line_num = 4 }, //*
|
||||
[RCC_GPIOF] = { .clk_domain = AHB1, .line_num = 5 }, //*
|
||||
[RCC_GPIOG] = { .clk_domain = AHB1, .line_num = 6 }, //*
|
||||
[RCC_UART4] = { .clk_domain = APB1, .line_num = 19 }, //unchanged
|
||||
[RCC_UART5] = { .clk_domain = APB1, .line_num = 20 }, //unchanged
|
||||
[RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, //unchanged
|
||||
[RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 }, //unchanged
|
||||
[RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 }, //unchanged
|
||||
[RCC_TIMER8] = { .clk_domain = APB2, .line_num = 1 }, //*
|
||||
[RCC_FSMC] = { .clk_domain = AHB3, .line_num = 0 }, //*
|
||||
[RCC_DAC] = { .clk_domain = APB1, .line_num = 29 }, //unchanged
|
||||
[RCC_DMA2] = { .clk_domain = AHB1, .line_num = 22 }, //*
|
||||
[RCC_SDIO] = { .clk_domain = APB2, .line_num = 11 }, //*
|
||||
[RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 }, //unchanged
|
||||
[RCC_TIMER9] = { .clk_domain = APB2, .line_num = 16 }, //*
|
||||
[RCC_TIMER10] = { .clk_domain = APB2, .line_num = 17 }, //*
|
||||
[RCC_TIMER11] = { .clk_domain = APB2, .line_num = 18 }, //*
|
||||
[RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 }, //unchanged
|
||||
[RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 }, //unchanged
|
||||
[RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 }, //unchanged
|
||||
[RCC_USBFS] = { .clk_domain = AHB2, .line_num = 7 }, //*
|
||||
[RCC_SYSCFG] = { .clk_domain = APB2, .line_num = 14 }, //*
|
||||
[RCC_SPI4] = { .clk_domain = APB1, .line_num = 15 },
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize the clock control system. Initializes the system
|
||||
* clock source to use the PLL driven by an external oscillator
|
||||
* @param sysclk_src system clock source, must be PLL
|
||||
* @param pll_src pll clock source, must be HSE
|
||||
* @param pll_mul pll multiplier
|
||||
*/
|
||||
|
||||
#define HSE_STARTUP_TIMEOUT ((uint16)0x0500) /*!< Time out for HSE start up */
|
||||
#define RCC_CFGR_HPRE_DIV1 ((uint32)0x00000000) /*!< SYSCLK not divided */
|
||||
#define RCC_CFGR_PPRE1_DIV2 ((uint32)0x00001000) /*!< HCLK divided by 2 */
|
||||
#define RCC_CFGR_PPRE1_DIV4 ((uint32)0x00001400) /*!< HCLK divided by 4 */
|
||||
#define RCC_CFGR_PPRE2_DIV1 ((uint32)0x00000000) /*!< HCLK not divided */
|
||||
#define RCC_CFGR_PPRE2_DIV2 ((uint32)0x00008000) /*!< HCLK divided by 2 */
|
||||
|
||||
#define RCC_PLLCFGR_PLLSRC_HSE ((uint32)0x00400000)
|
||||
|
||||
/******************* Bits definition for FLASH_ACR register *****************/
|
||||
//#define FLASH_ACR_LATENCY ((uint32_t)0x00000007)
|
||||
#define FLASH_ACR_LATENCY_0WS ((uint32)0x00000000)
|
||||
#define FLASH_ACR_LATENCY_1WS ((uint32)0x00000001)
|
||||
#define FLASH_ACR_LATENCY_2WS ((uint32)0x00000002)
|
||||
#define FLASH_ACR_LATENCY_3WS ((uint32)0x00000003)
|
||||
#define FLASH_ACR_LATENCY_4WS ((uint32)0x00000004)
|
||||
#define FLASH_ACR_LATENCY_5WS ((uint32)0x00000005)
|
||||
#define FLASH_ACR_LATENCY_6WS ((uint32)0x00000006)
|
||||
#define FLASH_ACR_LATENCY_7WS ((uint32)0x00000007)
|
||||
|
||||
#define FLASH_ACR_PRFTEN ((uint32)0x00000100)
|
||||
#define FLASH_ACR_ICEN ((uint32)0x00000200)
|
||||
#define FLASH_ACR_DCEN ((uint32)0x00000400)
|
||||
#define FLASH_ACR_ICRST ((uint32)0x00000800)
|
||||
#define FLASH_ACR_DCRST ((uint32)0x00001000)
|
||||
#define FLASH_ACR_BYTE0_ADDRESS ((uint32)0x40023C00)
|
||||
#define FLASH_ACR_BYTE2_ADDRESS ((uint32)0x40023C03)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__io uint32 CR; /*!< PWR power control register, Address offset: 0x00 */
|
||||
__io uint32 CSR; /*!< PWR power control/status register, Address offset: 0x04 */
|
||||
} PWR_TypeDef;
|
||||
|
||||
#define PWR_BASE (0x40007000)
|
||||
#define PWR ((PWR_TypeDef *) PWR_BASE)
|
||||
#define PWR_CR_VOS ((uint16)0x4000) /*!< Regulator voltage scaling output selection */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__io uint32 ACR; /*!< FLASH access control register, Address offset: 0x00 */
|
||||
__io uint32 KEYR; /*!< FLASH key register, Address offset: 0x04 */
|
||||
__io uint32 OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */
|
||||
__io uint32 SR; /*!< FLASH status register, Address offset: 0x0C */
|
||||
__io uint32 CR; /*!< FLASH control register, Address offset: 0x10 */
|
||||
__io uint32 OPTCR; /*!< FLASH option control register, Address offset: 0x14 */
|
||||
} FLASH_TypeDef;
|
||||
|
||||
#define FLASH_R_BASE (0x40023C00)
|
||||
#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE)
|
||||
#define RESET 0
|
||||
|
||||
typedef uint32 uint32_t;
|
||||
|
||||
void SetupClock72MHz()
|
||||
{
|
||||
uint32_t SystemCoreClock = 72000000;
|
||||
|
||||
/******************************************************************************/
|
||||
/* PLL (clocked by HSE) used as System clock source */
|
||||
/******************************************************************************/
|
||||
/************************* PLL Parameters *************************************/
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
|
||||
int PLL_M = 4;
|
||||
int PLL_N = 216;
|
||||
|
||||
/* SYSCLK = PLL_VCO / PLL_P */
|
||||
int PLL_P = 6;
|
||||
|
||||
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
|
||||
int PLL_Q = 9;
|
||||
|
||||
|
||||
uint32 StartUpCounter = 0, HSEStatus = 0;
|
||||
rcc_reg_map *RCC = RCC_BASE;
|
||||
|
||||
/* Enable HSE */
|
||||
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* Select regulator voltage output Scale 2 mode, System frequency up to 144 MHz */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
PWR->CR &= (uint32_t)~(PWR_CR_VOS);
|
||||
|
||||
/* HCLK = SYSCLK / 1*/
|
||||
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
/* PCLK2 = HCLK / 1*/
|
||||
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
|
||||
|
||||
/* PCLK1 = HCLK / 2*/
|
||||
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
|
||||
|
||||
// save bus clock values
|
||||
rcc_dev_clk_speed_table[RCC_AHB1] = (SystemCoreClock/1);
|
||||
rcc_dev_clk_speed_table[RCC_APB2] = (SystemCoreClock/1);
|
||||
rcc_dev_clk_speed_table[RCC_APB1] = (SystemCoreClock/2);
|
||||
|
||||
/* Configure the main PLL */
|
||||
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
|
||||
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
|
||||
|
||||
/* Enable the main PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* Wait till the main PLL is ready */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
|
||||
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;
|
||||
|
||||
/* Select the main PLL as system clock source */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till the main PLL is used as system clock source */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* If HSE fails to start-up, the application will have wrong clock
|
||||
configuration. User can add here some code to deal with this error */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupClock120MHz()
|
||||
{
|
||||
uint32_t SystemCoreClock = 120000000;
|
||||
|
||||
/******************************************************************************/
|
||||
/* PLL (clocked by HSE) used as System clock source */
|
||||
/******************************************************************************/
|
||||
/************************* PLL Parameters *************************************/
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
|
||||
int PLL_M = 8;
|
||||
int PLL_N = 240;
|
||||
|
||||
/* SYSCLK = PLL_VCO / PLL_P */
|
||||
int PLL_P = 2;
|
||||
|
||||
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
|
||||
int PLL_Q = 5;
|
||||
|
||||
|
||||
uint32 StartUpCounter = 0, HSEStatus = 0;
|
||||
rcc_reg_map *RCC = RCC_BASE;
|
||||
|
||||
/* Enable HSE */
|
||||
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* Select regulator voltage output Scale 2 mode, System frequency up to 144 MHz */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
PWR->CR &= (uint32_t)~(PWR_CR_VOS);
|
||||
|
||||
/* HCLK = SYSCLK / 1*/
|
||||
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
/* PCLK2 = HCLK / 2*/
|
||||
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
||||
|
||||
/* PCLK1 = HCLK / 4*/
|
||||
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
||||
|
||||
// save bus clock values
|
||||
rcc_dev_clk_speed_table[RCC_AHB1] = (SystemCoreClock/1);
|
||||
rcc_dev_clk_speed_table[RCC_APB2] = (SystemCoreClock/2);
|
||||
rcc_dev_clk_speed_table[RCC_APB1] = (SystemCoreClock/4);
|
||||
|
||||
/* Configure the main PLL */
|
||||
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
|
||||
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
|
||||
|
||||
/* Enable the main PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* Wait till the main PLL is ready */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
|
||||
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS;
|
||||
|
||||
/* Select the main PLL as system clock source */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till the main PLL is used as system clock source */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* If HSE fails to start-up, the application will have wrong clock
|
||||
configuration. User can add here some code to deal with this error */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupClock168MHz()
|
||||
{
|
||||
uint32_t SystemCoreClock = 168000000;
|
||||
|
||||
/******************************************************************************/
|
||||
/* PLL (clocked by HSE) used as System clock source */
|
||||
/******************************************************************************/
|
||||
/************************* PLL Parameters *************************************/
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
|
||||
int PLL_M = 8;
|
||||
int PLL_N = 336;
|
||||
|
||||
/* SYSCLK = PLL_VCO / PLL_P */
|
||||
int PLL_P = 2;
|
||||
|
||||
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
|
||||
int PLL_Q = 7;
|
||||
|
||||
|
||||
uint32 StartUpCounter = 0, HSEStatus = 0;
|
||||
rcc_reg_map *RCC = RCC_BASE;
|
||||
|
||||
/* Enable HSE */
|
||||
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
PWR->CR |= PWR_CR_VOS;
|
||||
|
||||
/* HCLK = SYSCLK / 1*/
|
||||
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
/* PCLK2 = HCLK / 2*/
|
||||
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
||||
|
||||
/* PCLK1 = HCLK / 4*/
|
||||
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
||||
|
||||
// save bus clock values
|
||||
rcc_dev_clk_speed_table[RCC_AHB1] = (SystemCoreClock/1);
|
||||
rcc_dev_clk_speed_table[RCC_APB2] = (SystemCoreClock/2);
|
||||
rcc_dev_clk_speed_table[RCC_APB1] = (SystemCoreClock/4);
|
||||
|
||||
/* Configure the main PLL */
|
||||
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
|
||||
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
|
||||
|
||||
/* Enable the main PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* Wait till the main PLL is ready */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
|
||||
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
|
||||
|
||||
/* Select the main PLL as system clock source */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till the main PLL is used as system clock source */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* If HSE fails to start-up, the application will have wrong clock
|
||||
configuration. User can add here some code to deal with this error */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rcc_clk_init(rcc_sysclk_src sysclk_src,
|
||||
rcc_pllsrc pll_src,
|
||||
rcc_pll_multiplier pll_mul) {
|
||||
|
||||
//SetupClock72MHz();
|
||||
#if STM32_TICKS_PER_US == 168
|
||||
SetupClock168MHz();
|
||||
#endif
|
||||
#if STM32_TICKS_PER_US == 120
|
||||
SetupClock120MHz();
|
||||
#endif
|
||||
#if STM32_TICKS_PER_US == 72
|
||||
SetupClock72MHz();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define PLL_M 8
|
||||
#define PLL_N 240
|
||||
/* SYSCLK = PLL_VCO / PLL_P */
|
||||
#define PLL_P 2
|
||||
|
||||
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
|
||||
#define PLL_Q 5
|
||||
|
||||
|
||||
void rcc_clk_init2(rcc_sysclk_src sysclk_src,
|
||||
rcc_pllsrc pll_src,
|
||||
rcc_pll_multiplier pll_mul) {
|
||||
|
||||
/******************************************************************************/
|
||||
/* PLL (clocked by HSE) used as System clock source */
|
||||
/******************************************************************************/
|
||||
uint32 StartUpCounter = 0, HSEStatus = 0;
|
||||
rcc_reg_map *pRCC = RCC_BASE;
|
||||
|
||||
/* Enable HSE */
|
||||
pRCC->CR |= RCC_CR_HSEON;
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = pRCC->CR & RCC_CR_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((pRCC->CR & RCC_CR_HSERDY) != 0)
|
||||
{
|
||||
HSEStatus = 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = 0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == 0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK / 1*/
|
||||
pRCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
/* PCLK2 = HCLK / 2*/
|
||||
pRCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
||||
|
||||
/* PCLK1 = HCLK / 4*/
|
||||
pRCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
||||
|
||||
/* Configure the main PLL */
|
||||
pRCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
|
||||
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
|
||||
|
||||
/* Enable the main PLL */
|
||||
pRCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* Wait till the main PLL is ready */
|
||||
while((pRCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
|
||||
((FLASH_TypeDef*)FLASH)->ACR = FLASH_ACR_PRFTEN |FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS;
|
||||
|
||||
/* Select the main PLL as system clock source */
|
||||
pRCC->CFGR &= ~RCC_CFGR_SW;
|
||||
pRCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till the main PLL is used as system clock source */
|
||||
while ((pRCC->CFGR & RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* If HSE fails to start-up, the application will have wrong clock
|
||||
configuration. User can add here some code to deal with this error */
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32 cfgr = 0;
|
||||
uint32 cr;
|
||||
|
||||
/* Assume that we're going to clock the chip off the PLL, fed by
|
||||
* the HSE */
|
||||
ASSERT(sysclk_src == RCC_CLKSRC_PLL &&
|
||||
pll_src == RCC_PLLSRC_HSE);
|
||||
|
||||
RCC_BASE->CFGR = pll_src | pll_mul;
|
||||
|
||||
/* Turn on the HSE */
|
||||
cr = RCC_BASE->CR;
|
||||
cr |= RCC_CR_HSEON;
|
||||
RCC_BASE->CR = cr;
|
||||
while (!(RCC_BASE->CR & RCC_CR_HSERDY))
|
||||
;
|
||||
|
||||
/* Now the PLL */
|
||||
cr |= RCC_CR_PLLON;
|
||||
RCC_BASE->CR = cr;
|
||||
while (!(RCC_BASE->CR & RCC_CR_PLLRDY))
|
||||
;
|
||||
|
||||
/* Finally, let's switch over to the PLL */
|
||||
cfgr &= ~RCC_CFGR_SW;
|
||||
cfgr |= RCC_CFGR_SW_PLL;
|
||||
RCC_BASE->CFGR = cfgr;
|
||||
while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn on the clock line on a peripheral
|
||||
* @param id Clock ID of the peripheral to turn on.
|
||||
*/
|
||||
void rcc_clk_enable(rcc_clk_id id) {
|
||||
static const __io uint32* enable_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1ENR,
|
||||
[APB2] = &RCC_BASE->APB2ENR,
|
||||
[AHB1] = &RCC_BASE->AHB1ENR,
|
||||
[AHB2] = &RCC_BASE->AHB2ENR,
|
||||
[AHB3] = &RCC_BASE->AHB3ENR,
|
||||
};
|
||||
|
||||
rcc_clk_domain clk_domain = rcc_dev_clk(id);
|
||||
__io uint32* enr = (__io uint32*)enable_regs[clk_domain];
|
||||
uint8 lnum = rcc_dev_table[id].line_num;
|
||||
|
||||
bb_peri_set_bit(enr, lnum, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn on the clock line on a peripheral
|
||||
* @param id Clock ID of the peripheral to turn on.
|
||||
*/
|
||||
void rcc_clk_disable(rcc_clk_id id) {
|
||||
static const __io uint32* enable_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1ENR,
|
||||
[APB2] = &RCC_BASE->APB2ENR,
|
||||
[AHB1] = &RCC_BASE->AHB1ENR,
|
||||
[AHB2] = &RCC_BASE->AHB2ENR,
|
||||
[AHB3] = &RCC_BASE->AHB3ENR,
|
||||
};
|
||||
|
||||
rcc_clk_domain clk_domain = rcc_dev_clk(id);
|
||||
__io uint32* enr = (__io uint32*)enable_regs[clk_domain];
|
||||
uint8 lnum = rcc_dev_table[id].line_num;
|
||||
|
||||
bb_peri_set_bit(enr, lnum, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset a peripheral.
|
||||
* @param id Clock ID of the peripheral to reset.
|
||||
*/
|
||||
void rcc_reset_dev(rcc_clk_id id) {
|
||||
static const __io uint32* reset_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1RSTR,
|
||||
[APB2] = &RCC_BASE->APB2RSTR,
|
||||
[AHB1] = &RCC_BASE->AHB1RSTR,
|
||||
[AHB2] = &RCC_BASE->AHB2RSTR,
|
||||
[AHB3] = &RCC_BASE->AHB3RSTR,
|
||||
};
|
||||
|
||||
rcc_clk_domain clk_domain = rcc_dev_clk(id);
|
||||
__io void* addr = (__io void*)reset_regs[clk_domain];
|
||||
uint8 lnum = rcc_dev_table[id].line_num;
|
||||
|
||||
bb_peri_set_bit(addr, lnum, 1);
|
||||
bb_peri_set_bit(addr, lnum, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's clock domain
|
||||
* @param id Clock ID of the peripheral whose clock domain to return
|
||||
* @return Clock source for the given clock ID
|
||||
*/
|
||||
rcc_clk_domain rcc_dev_clk(rcc_clk_id id) {
|
||||
return rcc_dev_table[id].clk_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's clock domain speed
|
||||
* @param id Clock ID of the peripheral whose clock domain speed to return
|
||||
* @return Clock speed for the given clock ID
|
||||
*/
|
||||
uint32 rcc_dev_clk_speed(rcc_clk_id id) {
|
||||
return rcc_dev_clk_speed_table[rcc_dev_clk(id)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's timer clock domain speed
|
||||
* @param id Clock ID of the peripheral whose clock domain speed to return
|
||||
* @return Clock speed for the given clock ID
|
||||
*/
|
||||
uint32 rcc_dev_timer_clk_speed(rcc_clk_id id) {
|
||||
return 2*rcc_dev_clk_speed(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the divider on a peripheral prescaler
|
||||
* @param prescaler prescaler to set
|
||||
* @param divider prescaler divider
|
||||
*/
|
||||
void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) {
|
||||
#if 0
|
||||
static const uint32 masks[] = {
|
||||
[RCC_PRESCALER_AHB] = RCC_CFGR_HPRE,
|
||||
[RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1,
|
||||
[RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2,
|
||||
[RCC_PRESCALER_USB] = RCC_CFGR_USBPRE,
|
||||
[RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE,
|
||||
};
|
||||
|
||||
uint32 cfgr = RCC_BASE->CFGR;
|
||||
cfgr &= ~masks[prescaler];
|
||||
cfgr |= divider;
|
||||
RCC_BASE->CFGR = cfgr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,600 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file rcc.h
|
||||
* @brief reset and clock control definitions and prototypes
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
#ifndef _RCC_H_
|
||||
#define _RCC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** RCC register map type */
|
||||
typedef struct
|
||||
{
|
||||
__io uint32 CR; /*!< RCC clock control register, Address offset: 0x00 */
|
||||
__io uint32 PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */
|
||||
__io uint32 CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */
|
||||
__io uint32 CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */
|
||||
__io uint32 AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */
|
||||
__io uint32 AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */
|
||||
__io uint32 AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */
|
||||
uint32 RESERVED0; /*!< Reserved, 0x1C */
|
||||
__io uint32 APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */
|
||||
__io uint32 APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */
|
||||
uint32 RESERVED1[2]; /*!< Reserved, 0x28-0x2C */
|
||||
__io uint32 AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */
|
||||
__io uint32 AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */
|
||||
__io uint32 AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */
|
||||
uint32 RESERVED2; /*!< Reserved, 0x3C */
|
||||
__io uint32 APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */
|
||||
__io uint32 APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */
|
||||
uint32 RESERVED3[2]; /*!< Reserved, 0x48-0x4C */
|
||||
__io uint32 AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */
|
||||
__io uint32 AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */
|
||||
__io uint32 AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */
|
||||
uint32 RESERVED4; /*!< Reserved, 0x5C */
|
||||
__io uint32 APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */
|
||||
__io uint32 APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */
|
||||
uint32 RESERVED5[2]; /*!< Reserved, 0x68-0x6C */
|
||||
__io uint32 BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */
|
||||
__io uint32 CSR; /*!< RCC clock control & status register, Address offset: 0x74 */
|
||||
uint32 RESERVED6[2]; /*!< Reserved, 0x78-0x7C */
|
||||
__io uint32 SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */
|
||||
__io uint32 PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */
|
||||
} rcc_reg_map;
|
||||
|
||||
/** RCC register map base pointer */
|
||||
//#define RCC_BASE ((struct rcc_reg_map*)0x40021000)
|
||||
#define RCC_BASE ((rcc_reg_map*)0x40023800)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Clock control register */
|
||||
|
||||
#define RCC_CR_PLLRDY_BIT 25
|
||||
#define RCC_CR_PLLON_BIT 24
|
||||
#define RCC_CR_CSSON_BIT 19
|
||||
#define RCC_CR_HSEBYP_BIT 18
|
||||
#define RCC_CR_HSERDY_BIT 17
|
||||
#define RCC_CR_HSEON_BIT 16
|
||||
#define RCC_CR_HSIRDY_BIT 1
|
||||
#define RCC_CR_HSION_BIT 0
|
||||
|
||||
#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT)
|
||||
#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT)
|
||||
#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT)
|
||||
#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT)
|
||||
#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT)
|
||||
#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT)
|
||||
#define RCC_CR_HSICAL (0xFF << 8)
|
||||
#define RCC_CR_HSITRIM (0x1F << 3)
|
||||
#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT)
|
||||
#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT)
|
||||
|
||||
/* Clock configuration register */
|
||||
|
||||
#define RCC_CFGR_USBPRE_BIT 22
|
||||
#define RCC_CFGR_PLLXTPRE_BIT 17
|
||||
#define RCC_CFGR_PLLSRC_BIT 16
|
||||
|
||||
#define RCC_CFGR_MCO (0x3 << 24)
|
||||
#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT)
|
||||
#define RCC_CFGR_PLLMUL (0xF << 18)
|
||||
#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT)
|
||||
#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT)
|
||||
#define RCC_CFGR_ADCPRE (0x3 << 14)
|
||||
#define RCC_CFGR_PPRE2 (0x7 << 11)
|
||||
#define RCC_CFGR_PPRE1 (0x7 << 8)
|
||||
#define RCC_CFGR_HPRE (0xF << 4)
|
||||
#define RCC_CFGR_SWS (0x3 << 2)
|
||||
#define RCC_CFGR_SWS_PLL (0x2 << 2)
|
||||
#define RCC_CFGR_SWS_HSE (0x1 << 2)
|
||||
#define RCC_CFGR_SW 0x3
|
||||
#define RCC_CFGR_SW_PLL 0x2
|
||||
#define RCC_CFGR_SW_HSE 0x1
|
||||
|
||||
/* Clock interrupt register */
|
||||
|
||||
#define RCC_CIR_CSSC_BIT 23
|
||||
#define RCC_CIR_PLLRDYC_BIT 20
|
||||
#define RCC_CIR_HSERDYC_BIT 19
|
||||
#define RCC_CIR_HSIRDYC_BIT 18
|
||||
#define RCC_CIR_LSERDYC_BIT 17
|
||||
#define RCC_CIR_LSIRDYC_BIT 16
|
||||
#define RCC_CIR_PLLRDYIE_BIT 12
|
||||
#define RCC_CIR_HSERDYIE_BIT 11
|
||||
#define RCC_CIR_HSIRDYIE_BIT 10
|
||||
#define RCC_CIR_LSERDYIE_BIT 9
|
||||
#define RCC_CIR_LSIRDYIE_BIT 8
|
||||
#define RCC_CIR_CSSF_BIT 7
|
||||
#define RCC_CIR_PLLRDYF_BIT 4
|
||||
#define RCC_CIR_HSERDYF_BIT 3
|
||||
#define RCC_CIR_HSIRDYF_BIT 2
|
||||
#define RCC_CIR_LSERDYF_BIT 1
|
||||
#define RCC_CIR_LSIRDYF_BIT 0
|
||||
|
||||
#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT)
|
||||
#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT)
|
||||
#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT)
|
||||
#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT)
|
||||
#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT)
|
||||
#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT)
|
||||
#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT)
|
||||
#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT)
|
||||
#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT)
|
||||
#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT)
|
||||
#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT)
|
||||
#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT)
|
||||
#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT)
|
||||
#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT)
|
||||
#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT)
|
||||
#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT)
|
||||
#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT)
|
||||
|
||||
/* APB2 peripheral reset register */
|
||||
|
||||
#define RCC_APB2RSTR_TIM11RST_BIT 21
|
||||
#define RCC_APB2RSTR_TIM10RST_BIT 20
|
||||
#define RCC_APB2RSTR_TIM9RST_BIT 19
|
||||
#define RCC_APB2RSTR_ADC3RST_BIT 15
|
||||
#define RCC_APB2RSTR_USART1RST_BIT 14
|
||||
#define RCC_APB2RSTR_TIM8RST_BIT 13
|
||||
#define RCC_APB2RSTR_SPI1RST_BIT 12
|
||||
#define RCC_APB2RSTR_TIM1RST_BIT 11
|
||||
#define RCC_APB2RSTR_ADC2RST_BIT 10
|
||||
#define RCC_APB2RSTR_ADC1RST_BIT 9
|
||||
#define RCC_APB2RSTR_IOPGRST_BIT 8
|
||||
#define RCC_APB2RSTR_IOPFRST_BIT 7
|
||||
#define RCC_APB2RSTR_IOPERST_BIT 6
|
||||
#define RCC_APB2RSTR_IOPDRST_BIT 5
|
||||
#define RCC_APB2RSTR_IOPCRST_BIT 4
|
||||
#define RCC_APB2RSTR_IOPBRST_BIT 3
|
||||
#define RCC_APB2RSTR_IOPARST_BIT 2
|
||||
#define RCC_APB2RSTR_AFIORST_BIT 0
|
||||
|
||||
#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT)
|
||||
#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT)
|
||||
#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT)
|
||||
#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT)
|
||||
#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT)
|
||||
#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT)
|
||||
#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT)
|
||||
#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT)
|
||||
#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT)
|
||||
#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT)
|
||||
#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT)
|
||||
|
||||
/* APB1 peripheral reset register */
|
||||
|
||||
#define RCC_APB1RSTR_DACRST_BIT 29
|
||||
#define RCC_APB1RSTR_PWRRST_BIT 28
|
||||
#define RCC_APB1RSTR_BKPRST_BIT 27
|
||||
#define RCC_APB1RSTR_CANRST_BIT 25
|
||||
#define RCC_APB1RSTR_USBRST_BIT 23
|
||||
#define RCC_APB1RSTR_I2C2RST_BIT 22
|
||||
#define RCC_APB1RSTR_I2C1RST_BIT 21
|
||||
#define RCC_APB1RSTR_UART5RST_BIT 20
|
||||
#define RCC_APB1RSTR_UART4RST_BIT 19
|
||||
#define RCC_APB1RSTR_USART3RST_BIT 18
|
||||
#define RCC_APB1RSTR_USART2RST_BIT 17
|
||||
#define RCC_APB1RSTR_SPI3RST_BIT 15
|
||||
#define RCC_APB1RSTR_SPI2RST_BIT 14
|
||||
#define RCC_APB1RSTR_WWDRST_BIT 11
|
||||
#define RCC_APB1RSTR_TIM14RST_BIT 8
|
||||
#define RCC_APB1RSTR_TIM13RST_BIT 7
|
||||
#define RCC_APB1RSTR_TIM12RST_BIT 6
|
||||
#define RCC_APB1RSTR_TIM7RST_BIT 5
|
||||
#define RCC_APB1RSTR_TIM6RST_BIT 4
|
||||
#define RCC_APB1RSTR_TIM5RST_BIT 3
|
||||
#define RCC_APB1RSTR_TIM4RST_BIT 2
|
||||
#define RCC_APB1RSTR_TIM3RST_BIT 1
|
||||
#define RCC_APB1RSTR_TIM2RST_BIT 0
|
||||
|
||||
#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT)
|
||||
#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT)
|
||||
#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT)
|
||||
#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT)
|
||||
#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT)
|
||||
#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT)
|
||||
#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT)
|
||||
#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT)
|
||||
#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT)
|
||||
#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT)
|
||||
#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT)
|
||||
#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT)
|
||||
#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT)
|
||||
#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT)
|
||||
#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT)
|
||||
#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT)
|
||||
|
||||
/* AHB peripheral clock enable register */
|
||||
|
||||
#define RCC_AHBENR_SDIOEN_BIT 10
|
||||
#define RCC_AHBENR_FSMCEN_BIT 8
|
||||
#define RCC_AHBENR_CRCEN_BIT 7
|
||||
#define RCC_AHBENR_FLITFEN_BIT 4
|
||||
#define RCC_AHBENR_SRAMEN_BIT 2
|
||||
#define RCC_AHBENR_DMA2EN_BIT 1
|
||||
#define RCC_AHBENR_DMA1EN_BIT 0
|
||||
|
||||
#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT)
|
||||
#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT)
|
||||
#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT)
|
||||
#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT)
|
||||
#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT)
|
||||
#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT)
|
||||
#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT)
|
||||
|
||||
/* APB2 peripheral clock enable register */
|
||||
|
||||
#define RCC_APB2ENR_TIM11EN_BIT 21
|
||||
#define RCC_APB2ENR_TIM10EN_BIT 20
|
||||
#define RCC_APB2ENR_TIM9EN_BIT 19
|
||||
#define RCC_APB2ENR_ADC3EN_BIT 15
|
||||
#define RCC_APB2ENR_USART1EN_BIT 14
|
||||
#define RCC_APB2ENR_TIM8EN_BIT 13
|
||||
#define RCC_APB2ENR_SPI1EN_BIT 12
|
||||
#define RCC_APB2ENR_TIM1EN_BIT 11
|
||||
#define RCC_APB2ENR_ADC2EN_BIT 10
|
||||
#define RCC_APB2ENR_ADC1EN_BIT 9
|
||||
#define RCC_APB2ENR_IOPGEN_BIT 8
|
||||
#define RCC_APB2ENR_IOPFEN_BIT 7
|
||||
#define RCC_APB2ENR_IOPEEN_BIT 6
|
||||
#define RCC_APB2ENR_IOPDEN_BIT 5
|
||||
#define RCC_APB2ENR_IOPCEN_BIT 4
|
||||
#define RCC_APB2ENR_IOPBEN_BIT 3
|
||||
#define RCC_APB2ENR_IOPAEN_BIT 2
|
||||
#define RCC_APB2ENR_AFIOEN_BIT 0
|
||||
|
||||
#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT)
|
||||
#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT)
|
||||
#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT)
|
||||
#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT)
|
||||
#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT)
|
||||
#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT)
|
||||
#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT)
|
||||
#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT)
|
||||
#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT)
|
||||
#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT)
|
||||
#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT)
|
||||
#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT)
|
||||
#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT)
|
||||
#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT)
|
||||
#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT)
|
||||
#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT)
|
||||
#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT)
|
||||
#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT)
|
||||
|
||||
/* APB1 peripheral clock enable register */
|
||||
|
||||
#define RCC_APB1ENR_DACEN_BIT 29
|
||||
#define RCC_APB1ENR_PWREN_BIT 28
|
||||
#define RCC_APB1ENR_BKPEN_BIT 27
|
||||
#define RCC_APB1ENR_CANEN_BIT 25
|
||||
#define RCC_APB1ENR_USBEN_BIT 23
|
||||
#define RCC_APB1ENR_I2C2EN_BIT 22
|
||||
#define RCC_APB1ENR_I2C1EN_BIT 21
|
||||
#define RCC_APB1ENR_UART5EN_BIT 20
|
||||
#define RCC_APB1ENR_UART4EN_BIT 19
|
||||
#define RCC_APB1ENR_USART3EN_BIT 18
|
||||
#define RCC_APB1ENR_USART2EN_BIT 17
|
||||
#define RCC_APB1ENR_SPI3EN_BIT 15
|
||||
#define RCC_APB1ENR_SPI2EN_BIT 14
|
||||
#define RCC_APB1ENR_WWDEN_BIT 11
|
||||
#define RCC_APB1ENR_TIM14EN_BIT 8
|
||||
#define RCC_APB1ENR_TIM13EN_BIT 7
|
||||
#define RCC_APB1ENR_TIM12EN_BIT 6
|
||||
#define RCC_APB1ENR_TIM7EN_BIT 5
|
||||
#define RCC_APB1ENR_TIM6EN_BIT 4
|
||||
#define RCC_APB1ENR_TIM5EN_BIT 3
|
||||
#define RCC_APB1ENR_TIM4EN_BIT 2
|
||||
#define RCC_APB1ENR_TIM3EN_BIT 1
|
||||
#define RCC_APB1ENR_TIM2EN_BIT 0
|
||||
|
||||
#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT)
|
||||
#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT)
|
||||
#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT)
|
||||
#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT)
|
||||
#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT)
|
||||
#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT)
|
||||
#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT)
|
||||
#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT)
|
||||
#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT)
|
||||
#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT)
|
||||
#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT)
|
||||
#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT)
|
||||
#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT)
|
||||
#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT)
|
||||
#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT)
|
||||
#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT)
|
||||
#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT)
|
||||
#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT)
|
||||
#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT)
|
||||
#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT)
|
||||
#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT)
|
||||
#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT)
|
||||
#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT)
|
||||
|
||||
/* Backup domain control register */
|
||||
|
||||
#define RCC_BDCR_BDRST_BIT 16
|
||||
#define RCC_BDCR_RTCEN_BIT 15
|
||||
#define RCC_BDCR_LSEBYP_BIT 2
|
||||
#define RCC_BDCR_LSERDY_BIT 1
|
||||
#define RCC_BDCR_LSEON_BIT 0
|
||||
|
||||
#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT)
|
||||
#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT)
|
||||
#define RCC_BDCR_RTCSEL (0x3 << 8)
|
||||
#define RCC_BDCR_RTCSEL_NONE (0x0 << 8)
|
||||
#define RCC_BDCR_RTCSEL_LSE (0x1 << 8)
|
||||
#define RCC_BDCR_RTCSEL_HSE (0x3 << 8)
|
||||
#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT)
|
||||
#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT)
|
||||
#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT)
|
||||
|
||||
/* Control/status register */
|
||||
|
||||
#define RCC_CSR_LPWRRSTF_BIT 31
|
||||
#define RCC_CSR_WWDGRSTF_BIT 30
|
||||
#define RCC_CSR_IWDGRSTF_BIT 29
|
||||
#define RCC_CSR_SFTRSTF_BIT 28
|
||||
#define RCC_CSR_PORRSTF_BIT 27
|
||||
#define RCC_CSR_PINRSTF_BIT 26
|
||||
#define RCC_CSR_RMVF_BIT 24
|
||||
#define RCC_CSR_LSIRDY_BIT 1
|
||||
#define RCC_CSR_LSION_BIT 0
|
||||
|
||||
#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT)
|
||||
#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT)
|
||||
#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT)
|
||||
#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT)
|
||||
#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT)
|
||||
#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT)
|
||||
#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT)
|
||||
#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT)
|
||||
#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT)
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* SYSCLK sources
|
||||
* @see rcc_clk_init()
|
||||
*/
|
||||
typedef enum rcc_sysclk_src {
|
||||
RCC_CLKSRC_HSI = 0x0,
|
||||
RCC_CLKSRC_HSE = 0x1,
|
||||
RCC_CLKSRC_PLL = 0x2,
|
||||
} rcc_sysclk_src;
|
||||
|
||||
/**
|
||||
* PLL entry clock source
|
||||
* @see rcc_clk_init()
|
||||
*/
|
||||
typedef enum rcc_pllsrc {
|
||||
RCC_PLLSRC_HSE = (0x1 << 16),
|
||||
RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16)
|
||||
} rcc_pllsrc;
|
||||
|
||||
/**
|
||||
* PLL multipliers
|
||||
* @see rcc_clk_init()
|
||||
*/
|
||||
typedef enum rcc_pll_multiplier {
|
||||
RCC_PLLMUL_2 = (0x0 << 18),
|
||||
RCC_PLLMUL_3 = (0x1 << 18),
|
||||
RCC_PLLMUL_4 = (0x2 << 18),
|
||||
RCC_PLLMUL_5 = (0x3 << 18),
|
||||
RCC_PLLMUL_6 = (0x4 << 18),
|
||||
RCC_PLLMUL_7 = (0x5 << 18),
|
||||
RCC_PLLMUL_8 = (0x6 << 18),
|
||||
RCC_PLLMUL_9 = (0x7 << 18),
|
||||
RCC_PLLMUL_10 = (0x8 << 18),
|
||||
RCC_PLLMUL_11 = (0x9 << 18),
|
||||
RCC_PLLMUL_12 = (0xA << 18),
|
||||
RCC_PLLMUL_13 = (0xB << 18),
|
||||
RCC_PLLMUL_14 = (0xC << 18),
|
||||
RCC_PLLMUL_15 = (0xD << 18),
|
||||
RCC_PLLMUL_16 = (0xE << 18),
|
||||
} rcc_pll_multiplier;
|
||||
|
||||
/**
|
||||
* @brief Identifies bus and clock line for a peripheral.
|
||||
*
|
||||
* Also generally useful as a unique identifier for that peripheral
|
||||
* (or its corresponding device struct).
|
||||
*/
|
||||
typedef enum rcc_clk_id {
|
||||
RCC_GPIOA,
|
||||
RCC_GPIOB,
|
||||
RCC_GPIOC,
|
||||
RCC_GPIOD,
|
||||
// RCC_AFIO,
|
||||
RCC_ADC1,
|
||||
RCC_ADC2,
|
||||
RCC_ADC3,
|
||||
RCC_USART1,
|
||||
RCC_USART2,
|
||||
RCC_USART3,
|
||||
RCC_TIMER1,
|
||||
RCC_TIMER2,
|
||||
RCC_TIMER3,
|
||||
RCC_TIMER4,
|
||||
RCC_SPI1,
|
||||
RCC_SPI2,
|
||||
RCC_DMA1,
|
||||
RCC_PWR,
|
||||
// RCC_BKP,
|
||||
RCC_I2C1,
|
||||
RCC_I2C2,
|
||||
RCC_CRC,
|
||||
// RCC_FLITF,
|
||||
// RCC_SRAM,
|
||||
RCC_GPIOE,
|
||||
RCC_GPIOF,
|
||||
RCC_GPIOG,
|
||||
RCC_UART4,
|
||||
RCC_UART5,
|
||||
RCC_TIMER5,
|
||||
RCC_TIMER6,
|
||||
RCC_TIMER7,
|
||||
RCC_TIMER8,
|
||||
RCC_FSMC,
|
||||
RCC_DAC,
|
||||
RCC_DMA2,
|
||||
RCC_SDIO,
|
||||
RCC_SPI3,
|
||||
RCC_TIMER9,
|
||||
RCC_TIMER10,
|
||||
RCC_TIMER11,
|
||||
RCC_TIMER12,
|
||||
RCC_TIMER13,
|
||||
RCC_TIMER14,
|
||||
RCC_USBFS,
|
||||
RCC_SYSCFG,
|
||||
RCC_SPI4
|
||||
} rcc_clk_id;
|
||||
|
||||
void rcc_clk_init(rcc_sysclk_src sysclk_src,
|
||||
rcc_pllsrc pll_src,
|
||||
rcc_pll_multiplier pll_mul);
|
||||
void rcc_clk_disable(rcc_clk_id device);
|
||||
void rcc_clk_enable(rcc_clk_id device);
|
||||
void rcc_reset_dev(rcc_clk_id device);
|
||||
|
||||
void SetupClock72MHz();
|
||||
void SetupClock120MHz();
|
||||
void SetupClock168MHz();
|
||||
|
||||
typedef enum rcc_clk_domain {
|
||||
RCC_APB1,
|
||||
RCC_APB2,
|
||||
RCC_AHB1,
|
||||
RCC_AHB2,
|
||||
RCC_AHB3
|
||||
} rcc_clk_domain;
|
||||
|
||||
rcc_clk_domain rcc_dev_clk(rcc_clk_id device);
|
||||
|
||||
uint32 rcc_dev_clk_speed(rcc_clk_id id);
|
||||
uint32 rcc_dev_timer_clk_speed(rcc_clk_id id);
|
||||
|
||||
/**
|
||||
* Prescaler identifiers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_prescaler {
|
||||
RCC_PRESCALER_AHB,
|
||||
RCC_PRESCALER_APB1,
|
||||
RCC_PRESCALER_APB2,
|
||||
RCC_PRESCALER_USB,
|
||||
RCC_PRESCALER_ADC
|
||||
} rcc_prescaler;
|
||||
|
||||
/**
|
||||
* ADC prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_adc_divider {
|
||||
RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14,
|
||||
RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14,
|
||||
RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14,
|
||||
RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14,
|
||||
} rcc_adc_divider;
|
||||
|
||||
/**
|
||||
* APB1 prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_apb1_divider {
|
||||
RCC_APB1_HCLK_DIV_1 = 0x0 << 8,
|
||||
RCC_APB1_HCLK_DIV_2 = 0x4 << 8,
|
||||
RCC_APB1_HCLK_DIV_4 = 0x5 << 8,
|
||||
RCC_APB1_HCLK_DIV_8 = 0x6 << 8,
|
||||
RCC_APB1_HCLK_DIV_16 = 0x7 << 8,
|
||||
} rcc_apb1_divider;
|
||||
|
||||
/**
|
||||
* APB2 prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_apb2_divider {
|
||||
RCC_APB2_HCLK_DIV_1 = 0x0 << 11,
|
||||
RCC_APB2_HCLK_DIV_2 = 0x4 << 11,
|
||||
RCC_APB2_HCLK_DIV_4 = 0x5 << 11,
|
||||
RCC_APB2_HCLK_DIV_8 = 0x6 << 11,
|
||||
RCC_APB2_HCLK_DIV_16 = 0x7 << 11,
|
||||
} rcc_apb2_divider;
|
||||
|
||||
/**
|
||||
* AHB prescaler dividers
|
||||
* @see rcc_set_prescaler()
|
||||
*/
|
||||
typedef enum rcc_ahb_divider {
|
||||
RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4,
|
||||
RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4,
|
||||
RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4,
|
||||
RCC_AHB_SYSCLK_DIV_8 = 0xA << 4,
|
||||
RCC_AHB_SYSCLK_DIV_16 = 0xB << 4,
|
||||
RCC_AHB_SYSCLK_DIV_32 = 0xC << 4,
|
||||
RCC_AHB_SYSCLK_DIV_64 = 0xD << 4,
|
||||
RCC_AHB_SYSCLK_DIV_128 = 0xD << 4,
|
||||
RCC_AHB_SYSCLK_DIV_256 = 0xE << 4,
|
||||
RCC_AHB_SYSCLK_DIV_512 = 0xF << 4,
|
||||
} rcc_ahb_divider;
|
||||
|
||||
void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,189 @@
|
|||
/******************************************************************************
|
||||
* 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 ring_buffer.h
|
||||
* @brief Simple circular buffer
|
||||
*
|
||||
* This implementation is not thread-safe. In particular, none of
|
||||
* these functions is guaranteed re-entrant.
|
||||
*/
|
||||
|
||||
#ifndef _RING_BUFFER_H_
|
||||
#define _RING_BUFFER_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ring buffer type.
|
||||
*
|
||||
* The buffer is empty when head == tail.
|
||||
*
|
||||
* The buffer is full when the head is one byte in front of the tail,
|
||||
* modulo buffer length.
|
||||
*
|
||||
* One byte is left free to distinguish empty from full. */
|
||||
typedef struct ring_buffer {
|
||||
volatile uint8 *buf; /**< Buffer items are stored into */
|
||||
uint16 head; /**< Index of the next item to remove */
|
||||
uint16 tail; /**< Index where the next item will get inserted */
|
||||
uint16 size; /**< Buffer capacity minus one */
|
||||
} ring_buffer;
|
||||
|
||||
/**
|
||||
* Initialise a ring buffer.
|
||||
*
|
||||
* @param rb Instance to initialise
|
||||
*
|
||||
* @param size Number of items in buf. The ring buffer will always
|
||||
* leave one element unoccupied, so the maximum number of
|
||||
* elements it can store will be size - 1. Thus, size
|
||||
* must be at least 2.
|
||||
*
|
||||
* @param buf Buffer to store items into
|
||||
*/
|
||||
static inline void rb_init(ring_buffer *rb, uint16 size, uint8 *buf) {
|
||||
rb->head = 0;
|
||||
rb->tail = 0;
|
||||
rb->size = size - 1;
|
||||
rb->buf = buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the number of elements stored in the ring buffer.
|
||||
* @param rb Buffer whose elements to count.
|
||||
*/
|
||||
static inline uint16 rb_full_count(ring_buffer *rb) {
|
||||
__io ring_buffer *arb = rb;
|
||||
int32 size = arb->tail - arb->head;
|
||||
if (arb->tail < arb->head) {
|
||||
size += arb->size + 1;
|
||||
}
|
||||
return (uint16)size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if and only if the ring buffer is full.
|
||||
* @param rb Buffer to test.
|
||||
*/
|
||||
static inline int rb_is_full(ring_buffer *rb) {
|
||||
return (rb->tail + 1 == rb->head) ||
|
||||
(rb->tail == rb->size && rb->head == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if and only if the ring buffer is empty.
|
||||
* @param rb Buffer to test.
|
||||
*/
|
||||
static inline int rb_is_empty(ring_buffer *rb) {
|
||||
return rb->head == rb->tail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append element onto the end of a ring buffer.
|
||||
* @param rb Buffer to append onto.
|
||||
* @param element Value to append.
|
||||
*/
|
||||
static inline void rb_insert(ring_buffer *rb, uint8 element) {
|
||||
rb->buf[rb->tail] = element;
|
||||
rb->tail = (rb->tail == rb->size) ? 0 : rb->tail + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove and return the first item from a ring buffer.
|
||||
* @param rb Buffer to remove from, must contain at least one element.
|
||||
*/
|
||||
static inline uint8 rb_remove(ring_buffer *rb) {
|
||||
uint8 ch = rb->buf[rb->head];
|
||||
rb->head = (rb->head == rb->size) ? 0 : rb->head + 1;
|
||||
return ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempt to remove the first item from a ring buffer.
|
||||
*
|
||||
* If the ring buffer is nonempty, removes and returns its first item.
|
||||
* If it is empty, does nothing and returns a negative value.
|
||||
*
|
||||
* @param rb Buffer to attempt to remove from.
|
||||
*/
|
||||
static inline int16 rb_safe_remove(ring_buffer *rb) {
|
||||
return rb_is_empty(rb) ? -1 : rb_remove(rb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempt to insert an element into a ring buffer.
|
||||
*
|
||||
* @param rb Buffer to insert into.
|
||||
* @param element Value to insert into rb.
|
||||
* @sideeffect If rb is not full, appends element onto buffer.
|
||||
* @return If element was appended, then true; otherwise, false. */
|
||||
static inline int rb_safe_insert(ring_buffer *rb, uint8 element) {
|
||||
if (rb_is_full(rb)) {
|
||||
return 0;
|
||||
}
|
||||
rb_insert(rb, element);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append an item onto the end of a non-full ring buffer.
|
||||
*
|
||||
* If the buffer is full, removes its first item, then inserts the new
|
||||
* element at the end.
|
||||
*
|
||||
* @param rb Ring buffer to insert into.
|
||||
* @param element Value to insert into ring buffer.
|
||||
* @return On success, returns -1. If an element was popped, returns
|
||||
* the popped value.
|
||||
*/
|
||||
static inline int rb_push_insert(ring_buffer *rb, uint8 element) {
|
||||
int ret = -1;
|
||||
if (rb_is_full(rb)) {
|
||||
ret = rb_remove(rb);
|
||||
}
|
||||
rb_insert(rb, element);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discard all items from a ring buffer.
|
||||
* @param rb Ring buffer to discard all items from.
|
||||
*/
|
||||
static inline void rb_reset(ring_buffer *rb) {
|
||||
rb->tail = rb->head;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
# Standard things
|
||||
sp := $(sp).x
|
||||
dirstack_$(sp) := $(d)
|
||||
d := $(dir)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)
|
||||
ifneq ($(MCU_FAMILY), STM32F2)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usb
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usb/usb_lib
|
||||
LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH) -I$(LIBMAPLE_PATH)/usb -I$(LIBMAPLE_PATH)/usb/usb_lib
|
||||
else
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/STM32_USB_Device_Library/Core/src
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/STM32_USB_Device_Library/Class/cdc/src
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/STM32_USB_OTG_Driver/src
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/VCP
|
||||
LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH) -I$(LIBMAPLE_PATH)/usbF4
|
||||
endif
|
||||
|
||||
|
||||
# Local flags
|
||||
CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall
|
||||
#-Werror
|
||||
|
||||
# Local rules and targets
|
||||
# bkp.c
|
||||
|
||||
cSRCS_$(d) := adc.c \
|
||||
dac.c \
|
||||
dma.c \
|
||||
exti.c \
|
||||
flash.c \
|
||||
fsmc.c \
|
||||
gpio.c \
|
||||
iwdg.c \
|
||||
nvic.c \
|
||||
pwr.c \
|
||||
i2c.c \
|
||||
rcc.c \
|
||||
spi.c \
|
||||
syscalls.c \
|
||||
systick.c \
|
||||
timer.c \
|
||||
usart.c \
|
||||
util.c
|
||||
|
||||
ifneq ($(MCU_FAMILY), STM32F2)
|
||||
cSRCS_$(d) += \
|
||||
usb/descriptors.c \
|
||||
usb/usb.c \
|
||||
usb/usb_callbacks.c \
|
||||
usb/usb_hardware.c \
|
||||
usb/usb_lib/usb_core.c \
|
||||
usb/usb_lib/usb_init.c \
|
||||
usb/usb_lib/usb_int.c \
|
||||
usb/usb_lib/usb_mem.c \
|
||||
usb/usb_lib/usb_regs.c
|
||||
else
|
||||
V=1
|
||||
cSRCS_$(d) += \
|
||||
usbF4/STM32_USB_Device_Library/Core/src/usbd_core.c \
|
||||
usbF4/STM32_USB_Device_Library/Core/src/usbd_ioreq.c \
|
||||
usbF4/STM32_USB_Device_Library/Core/src/usbd_req.c \
|
||||
usbF4/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c \
|
||||
usbF4/STM32_USB_OTG_Driver/src/usb_dcd.c \
|
||||
usbF4/STM32_USB_OTG_Driver/src/usb_core.c \
|
||||
usbF4/STM32_USB_OTG_Driver/src/usb_dcd_int.c \
|
||||
usbF4/VCP/usb_bsp.c \
|
||||
usbF4/VCP/usbd_cdc_vcp.c \
|
||||
usbF4/VCP/usbd_desc.c \
|
||||
usbF4/VCP/usbd_usr.c \
|
||||
usbF4/usb.c \
|
||||
usbF4/VCP/misc.c
|
||||
endif
|
||||
|
||||
ifneq ($(MCU_FAMILY), STM32F2)
|
||||
cSRCS_$(d) += bkp.c
|
||||
endif
|
||||
|
||||
sSRCS_$(d) := exc.S
|
||||
|
||||
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
|
||||
sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
|
||||
|
||||
OBJS_$(d) := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o)
|
||||
DEPS_$(d) := $(OBJS_$(d):%.o=%.d)
|
||||
|
||||
$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d))
|
||||
$(OBJS_$(d)): TGT_ASFLAGS :=
|
||||
|
||||
TGT_BIN += $(OBJS_$(d))
|
||||
|
||||
# Standard things
|
||||
-include $(DEPS_$(d))
|
||||
d := $(dirstack_$(sp))
|
||||
sp := $(basename $(sp))
|
|
@ -0,0 +1,65 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file scb.h
|
||||
* @brief System control block header
|
||||
*/
|
||||
|
||||
#include "libmaple_types.h"
|
||||
|
||||
#ifndef _SCB_H_
|
||||
#define _SCB_H_
|
||||
|
||||
/** System control block register map type */
|
||||
typedef struct scb_reg_map {
|
||||
__io uint32 CPUID; /**< CPU ID Base Register */
|
||||
__io uint32 ICSR; /**< Interrupt Control State Register */
|
||||
__io uint32 VTOR; /**< Vector Table Offset Register */
|
||||
__io uint32 AIRCR; /**< Application Interrupt / Reset Control Register */
|
||||
__io uint32 SCR; /**< System Control Register */
|
||||
__io uint32 CCR; /**< Configuration Control Register */
|
||||
__io uint8 SHP[12]; /**< System Handlers Priority Registers
|
||||
(4-7, 8-11, 12-15) */
|
||||
__io uint32 SHCSR; /**< System Handler Control and State Register */
|
||||
__io uint32 CFSR; /**< Configurable Fault Status Register */
|
||||
__io uint32 HFSR; /**< Hard Fault Status Register */
|
||||
__io uint32 DFSR; /**< Debug Fault Status Register */
|
||||
__io uint32 MMFAR; /**< Mem Manage Address Register */
|
||||
__io uint32 BFAR; /**< Bus Fault Address Register */
|
||||
__io uint32 AFSR; /**< Auxiliary Fault Status Register */
|
||||
__io uint32 PFR[2]; /**< Processor Feature Register */
|
||||
__io uint32 DFR; /**< Debug Feature Register */
|
||||
__io uint32 ADR; /**< Auxiliary Feature Register */
|
||||
__io uint32 MMFR[4]; /**< Memory Model Feature Register */
|
||||
__io uint32 ISAR[5]; /**< ISA Feature Register */
|
||||
} scb_reg_map;
|
||||
|
||||
/** System control block register map base pointer */
|
||||
#define SCB_BASE ((struct scb_reg_map*)0xE000ED00)
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file spi.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Serial Peripheral Interface (SPI) support.
|
||||
* Currently, there is no Integrated Interchip Sound (I2S) support.
|
||||
*/
|
||||
|
||||
#include "spi.h"
|
||||
#include "bitband.h"
|
||||
|
||||
static void spi_reconfigure(spi_dev *dev, uint32 cr1_config);
|
||||
|
||||
/*
|
||||
* SPI devices
|
||||
*/
|
||||
|
||||
static spi_dev spi1 = {
|
||||
.regs = SPI1_BASE,
|
||||
.clk_id = RCC_SPI1,
|
||||
.irq_num = NVIC_SPI1,
|
||||
};
|
||||
/** SPI device 1 */
|
||||
spi_dev *SPI1 = &spi1;
|
||||
|
||||
static spi_dev spi2 = {
|
||||
.regs = SPI2_BASE,
|
||||
.clk_id = RCC_SPI2,
|
||||
.irq_num = NVIC_SPI2,
|
||||
};
|
||||
/** SPI device 2 */
|
||||
spi_dev *SPI2 = &spi2;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
static spi_dev spi3 = {
|
||||
.regs = SPI3_BASE,
|
||||
.clk_id = RCC_SPI3,
|
||||
.irq_num = NVIC_SPI3,
|
||||
};
|
||||
/** SPI device 3 */
|
||||
spi_dev *SPI3 = &spi3;
|
||||
#endif
|
||||
|
||||
#ifdef STM32F2
|
||||
static spi_dev spi4 = {
|
||||
.regs = SPI3_BASE,
|
||||
.clk_id = RCC_SPI4,
|
||||
.irq_num = NVIC_SPI3,
|
||||
};
|
||||
/** SPI device 3 remapped*/
|
||||
spi_dev *SPI4 = &spi4;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SPI convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize and reset a SPI device.
|
||||
* @param dev Device to initialize and reset.
|
||||
*/
|
||||
void spi_init(spi_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure GPIO bit modes for use as a SPI port's pins.
|
||||
* @param as_master If true, configure bits for use as a bus master.
|
||||
* Otherwise, configure bits for use as slave.
|
||||
* @param nss_dev NSS pin's GPIO device
|
||||
* @param comm_dev SCK, MISO, MOSI pins' GPIO device
|
||||
* @param nss_bit NSS pin's GPIO bit on nss_dev
|
||||
* @param sck_bit SCK pin's GPIO bit on comm_dev
|
||||
* @param miso_bit MISO pin's GPIO bit on comm_dev
|
||||
* @param mosi_bit MOSI pin's GPIO bit on comm_dev
|
||||
*/
|
||||
void spi_gpio_cfg(uint8 as_master,
|
||||
gpio_dev *nss_dev,
|
||||
uint8 nss_bit,
|
||||
gpio_dev *comm_dev,
|
||||
uint8 sck_bit,
|
||||
uint8 miso_bit,
|
||||
uint8 mosi_bit) {
|
||||
if (as_master) {
|
||||
if(nss_dev != NULL) {
|
||||
gpio_set_mode(nss_dev, nss_bit, GPIO_OUTPUT_PP);
|
||||
}
|
||||
gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP);
|
||||
//gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(comm_dev, miso_bit, GPIO_AF_INPUT_PD);
|
||||
gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP);
|
||||
} else {
|
||||
if(nss_dev != NULL) {
|
||||
gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING);
|
||||
}
|
||||
gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure and enable a SPI device as bus master.
|
||||
*
|
||||
* The device's peripheral will be disabled before being reconfigured.
|
||||
*
|
||||
* @param dev Device to configure as bus master
|
||||
* @param baud Bus baud rate
|
||||
* @param mode SPI mode
|
||||
* @param flags Logical OR of spi_cfg_flag values.
|
||||
* @see spi_cfg_flag
|
||||
*/
|
||||
void spi_master_enable(spi_dev *dev,
|
||||
spi_baud_rate baud,
|
||||
spi_mode mode,
|
||||
uint32 flags) {
|
||||
spi_reconfigure(dev, baud | flags | SPI_CR1_MSTR | mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure and enable a SPI device as a bus slave.
|
||||
*
|
||||
* The device's peripheral will be disabled before being reconfigured.
|
||||
*
|
||||
* @param dev Device to configure as a bus slave
|
||||
* @param mode SPI mode
|
||||
* @param flags Logical OR of spi_cfg_flag values.
|
||||
* @see spi_cfg_flag
|
||||
*/
|
||||
void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
|
||||
spi_reconfigure(dev, flags | mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Nonblocking SPI transmit.
|
||||
* @param dev SPI port to use for transmission
|
||||
* @param buf Buffer to transmit. The sizeof buf's elements are
|
||||
* inferred from dev's data frame format (i.e., are
|
||||
* correctly treated as 8-bit or 16-bit quantities).
|
||||
* @param len Maximum number of elements to transmit.
|
||||
* @return Number of elements transmitted.
|
||||
*/
|
||||
uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) {
|
||||
uint32 txed = 0;
|
||||
uint8 byte_frame = spi_dff(dev) == SPI_DFF_8_BIT;
|
||||
while (spi_is_tx_empty(dev) && (txed < len)) {
|
||||
if (byte_frame) {
|
||||
dev->regs->DR = ((const uint8*)buf)[txed++];
|
||||
} else {
|
||||
dev->regs->DR = ((const uint16*)buf)[txed++];
|
||||
}
|
||||
}
|
||||
return txed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call a function on each SPI port
|
||||
* @param fn Function to call.
|
||||
*/
|
||||
void spi_foreach(void (*fn)(spi_dev*)) {
|
||||
fn(SPI1);
|
||||
fn(SPI2);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
fn(SPI3);
|
||||
#endif
|
||||
#ifdef STM32F2
|
||||
fn(SPI4);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a SPI peripheral
|
||||
* @param dev Device to enable
|
||||
*/
|
||||
void spi_peripheral_enable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a SPI peripheral
|
||||
* @param dev Device to disable
|
||||
*/
|
||||
void spi_peripheral_disable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA requests whenever the transmit buffer is empty
|
||||
* @param dev SPI device on which to enable TX DMA requests
|
||||
*/
|
||||
void spi_tx_dma_enable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable DMA requests whenever the transmit buffer is empty
|
||||
* @param dev SPI device on which to disable TX DMA requests
|
||||
*/
|
||||
void spi_tx_dma_disable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA requests whenever the receive buffer is empty
|
||||
* @param dev SPI device on which to enable RX DMA requests
|
||||
*/
|
||||
void spi_rx_dma_enable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable DMA requests whenever the receive buffer is empty
|
||||
* @param dev SPI device on which to disable RX DMA requests
|
||||
*/
|
||||
void spi_rx_dma_disable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* SPI auxiliary routines
|
||||
*/
|
||||
|
||||
static void spi_reconfigure(spi_dev *dev, uint32 cr1_config) {
|
||||
spi_irq_disable(dev, SPI_INTERRUPTS_ALL);
|
||||
spi_peripheral_disable(dev);
|
||||
dev->regs->CR1 = cr1_config;
|
||||
spi_peripheral_enable(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handlers (TODO)
|
||||
*/
|
|
@ -0,0 +1,459 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file spi.h
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Serial Peripheral Interface (SPI) and Integrated
|
||||
* Interchip Sound (I2S) peripheral support.
|
||||
*
|
||||
* I2S support is currently limited to register maps and bit definitions.
|
||||
*/
|
||||
|
||||
#ifndef _SPI_H_
|
||||
#define _SPI_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
#include "gpio.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register maps
|
||||
*/
|
||||
|
||||
/** SPI register map type. */
|
||||
typedef struct spi_reg_map {
|
||||
__io uint32 CR1; /**< Control register 1 */
|
||||
__io uint32 CR2; /**< Control register 2 */
|
||||
__io uint32 SR; /**< Status register */
|
||||
__io uint32 DR; /**< Data register */
|
||||
__io uint32 CRCPR; /**< CRC polynomial register */
|
||||
__io uint32 RXCRCR; /**< RX CRC register */
|
||||
__io uint32 TXCRCR; /**< TX CRC register */
|
||||
__io uint32 I2SCFGR; /**< I2S configuration register */
|
||||
__io uint32 I2SPR; /**< I2S prescaler register */
|
||||
} spi_reg_map;
|
||||
|
||||
/** SPI1 register map base pointer */
|
||||
#define SPI1_BASE ((struct spi_reg_map*)0x40013000)
|
||||
/** SPI2 register map base pointer */
|
||||
#define SPI2_BASE ((struct spi_reg_map*)0x40003800)
|
||||
/** SPI3 register map base pointer */
|
||||
#define SPI3_BASE ((struct spi_reg_map*)0x40003C00)
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Control register 1 */
|
||||
|
||||
#define SPI_CR1_BIDIMODE_BIT 15
|
||||
#define SPI_CR1_BIDIOE_BIT 14
|
||||
#define SPI_CR1_CRCEN_BIT 13
|
||||
#define SPI_CR1_CRCNEXT_BIT 12
|
||||
#define SPI_CR1_DFF_BIT 11
|
||||
#define SPI_CR1_RXONLY_BIT 10
|
||||
#define SPI_CR1_SSM_BIT 9
|
||||
#define SPI_CR1_SSI_BIT 8
|
||||
#define SPI_CR1_LSBFIRST_BIT 7
|
||||
#define SPI_CR1_SPE_BIT 6
|
||||
#define SPI_CR1_MSTR_BIT 2
|
||||
#define SPI_CR1_CPOL_BIT 1
|
||||
#define SPI_CR1_CPHA_BIT 0
|
||||
|
||||
#define SPI_CR1_BIDIMODE BIT(SPI_CR1_BIDIMODE_BIT)
|
||||
#define SPI_CR1_BIDIMODE_2_LINE (0x0 << SPI_CR1_BIDIMODE_BIT)
|
||||
#define SPI_CR1_BIDIMODE_1_LINE (0x1 << SPI_CR1_BIDIMODE_BIT)
|
||||
#define SPI_CR1_BIDIOE BIT(SPI_CR1_BIDIOE_BIT)
|
||||
#define SPI_CR1_CRCEN BIT(SPI_CR1_CRCEN_BIT)
|
||||
#define SPI_CR1_CRCNEXT BIT(SPI_CR1_CRCNEXT_BIT)
|
||||
#define SPI_CR1_DFF BIT(SPI_CR1_DFF_BIT)
|
||||
#define SPI_CR1_DFF_8_BIT (0x0 << SPI_CR1_DFF_BIT)
|
||||
#define SPI_CR1_DFF_16_BIT (0x1 << SPI_CR1_DFF_BIT)
|
||||
#define SPI_CR1_RXONLY BIT(SPI_CR1_RXONLY_BIT)
|
||||
#define SPI_CR1_SSM BIT(SPI_CR1_SSM_BIT)
|
||||
#define SPI_CR1_SSI BIT(SPI_CR1_SSI_BIT)
|
||||
#define SPI_CR1_LSBFIRST BIT(SPI_CR1_LSBFIRST_BIT)
|
||||
#define SPI_CR1_SPE BIT(SPI_CR1_SPE_BIT)
|
||||
#define SPI_CR1_BR (0x7 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_2 (0x0 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_4 (0x1 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_8 (0x2 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_16 (0x3 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_32 (0x4 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_64 (0x5 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_128 (0x6 << 3)
|
||||
#define SPI_CR1_BR_PCLK_DIV_256 (0x7 << 3)
|
||||
#define SPI_CR1_MSTR BIT(SPI_CR1_MSTR_BIT)
|
||||
#define SPI_CR1_CPOL BIT(SPI_CR1_CPOL_BIT)
|
||||
#define SPI_CR1_CPOL_LOW (0x0 << SPI_CR1_CPOL_BIT)
|
||||
#define SPI_CR1_CPOL_HIGH (0x1 << SPI_CR1_CPOL_BIT)
|
||||
#define SPI_CR1_CPHA BIT(SPI_CR1_CPHA_BIT)
|
||||
|
||||
/* Control register 2 */
|
||||
|
||||
/* RM0008-ism: SPI CR2 has "TXDMAEN" and "RXDMAEN" bits, while the
|
||||
* USARTs have CR3 "DMAR" and "DMAT" bits. */
|
||||
|
||||
#define SPI_CR2_TXEIE_BIT 7
|
||||
#define SPI_CR2_RXNEIE_BIT 6
|
||||
#define SPI_CR2_ERRIE_BIT 5
|
||||
#define SPI_CR2_SSOE_BIT 2
|
||||
#define SPI_CR2_TXDMAEN_BIT 1
|
||||
#define SPI_CR2_RXDMAEN_BIT 0
|
||||
|
||||
#define SPI_CR2_TXEIE BIT(SPI_CR2_TXEIE_BIT)
|
||||
#define SPI_CR2_RXNEIE BIT(SPI_CR2_RXNEIE_BIT)
|
||||
#define SPI_CR2_ERRIE BIT(SPI_CR2_ERRIE_BIT)
|
||||
#define SPI_CR2_SSOE BIT(SPI_CR2_SSOE_BIT)
|
||||
#define SPI_CR2_TXDMAEN BIT(SPI_CR2_TXDMAEN_BIT)
|
||||
#define SPI_CR2_RXDMAEN BIT(SPI_CR2_RXDMAEN_BIT)
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define SPI_SR_BSY_BIT 7
|
||||
#define SPI_SR_OVR_BIT 6
|
||||
#define SPI_SR_MODF_BIT 5
|
||||
#define SPI_SR_CRCERR_BIT 4
|
||||
#define SPI_SR_UDR_BIT 3
|
||||
#define SPI_SR_CHSIDE_BIT 2
|
||||
#define SPI_SR_TXE_BIT 1
|
||||
#define SPI_SR_RXNE_BIT 0
|
||||
|
||||
#define SPI_SR_BSY BIT(SPI_SR_BSY_BIT)
|
||||
#define SPI_SR_OVR BIT(SPI_SR_OVR_BIT)
|
||||
#define SPI_SR_MODF BIT(SPI_SR_MODF_BIT)
|
||||
#define SPI_SR_CRCERR BIT(SPI_SR_CRCERR_BIT)
|
||||
#define SPI_SR_UDR BIT(SPI_SR_UDR_BIT)
|
||||
#define SPI_SR_CHSIDE BIT(SPI_SR_CHSIDE_BIT)
|
||||
#define SPI_SR_CHSIDE_LEFT (0x0 << SPI_SR_CHSIDE_BIT)
|
||||
#define SPI_SR_CHSIDE_RIGHT (0x1 << SPI_SR_CHSIDE_BIT)
|
||||
#define SPI_SR_TXE BIT(SPI_SR_TXE_BIT)
|
||||
#define SPI_SR_RXNE BIT(SPI_SR_RXNE_BIT)
|
||||
|
||||
/* I2S configuration register */
|
||||
|
||||
/* RM0008-ism: CR1 has "CPOL", I2SCFGR has "CKPOL". */
|
||||
|
||||
#define SPI_I2SCFGR_I2SMOD_BIT 11
|
||||
#define SPI_I2SCFGR_I2SE_BIT 10
|
||||
#define SPI_I2SCFGR_PCMSYNC_BIT 7
|
||||
#define SPI_I2SCFGR_CKPOL_BIT 3
|
||||
#define SPI_I2SCFGR_CHLEN_BIT 0
|
||||
|
||||
#define SPI_I2SCFGR_I2SMOD BIT(SPI_I2SCFGR_I2SMOD_BIT)
|
||||
#define SPI_I2SCFGR_I2SMOD_SPI (0x0 << SPI_I2SCFGR_I2SMOD_BIT)
|
||||
#define SPI_I2SCFGR_I2SMOD_I2S (0x1 << SPI_I2SCFGR_I2SMOD_BIT)
|
||||
#define SPI_I2SCFGR_I2SE BIT(SPI_I2SCFGR_I2SE_BIT)
|
||||
#define SPI_I2SCFGR_I2SCFG (0x3 << 8)
|
||||
#define SPI_I2SCFGR_I2SCFG_SLAVE_TX (0x0 << 8)
|
||||
#define SPI_I2SCFGR_I2SCFG_SLAVE_RX (0x1 << 8)
|
||||
#define SPI_I2SCFGR_I2SCFG_MASTER_TX (0x2 << 8)
|
||||
#define SPI_I2SCFGR_I2SCFG_MASTER_RX (0x3 << 8)
|
||||
#define SPI_I2SCFGR_PCMSYNC BIT(SPI_I2SCFGR_PCMSYNC_BIT)
|
||||
#define SPI_I2SCFGR_PCMSYNC_SHORT (0x0 << SPI_I2SCFGR_PCMSYNC_BIT)
|
||||
#define SPI_I2SCFGR_PCMSYNC_LONG (0x1 << SPI_I2SCFGR_PCMSYNC_BIT)
|
||||
#define SPI_I2SCFGR_I2SSTD (0x3 << 4)
|
||||
#define SPI_I2SCFGR_I2SSTD_PHILLIPS (0x0 << 4)
|
||||
#define SPI_I2SCFGR_I2SSTD_MSB (0x1 << 4)
|
||||
#define SPI_I2SCFGR_I2SSTD_LSB (0x2 << 4)
|
||||
#define SPI_I2SCFGR_I2SSTD_PCM (0x3 << 4)
|
||||
#define SPI_I2SCFGR_CKPOL BIT(SPI_I2SCFGR_CKPOL_BIT)
|
||||
#define SPI_I2SCFGR_CKPOL_LOW (0x0 << SPI_I2SCFGR_CKPOL_BIT)
|
||||
#define SPI_I2SCFGR_CKPOL_HIGH (0x1 << SPI_I2SCFGR_CKPOL_BIT)
|
||||
#define SPI_I2SCFGR_DATLEN (0x3 << 1)
|
||||
#define SPI_I2SCFGR_DATLEN_16_BIT (0x0 << 1)
|
||||
#define SPI_I2SCFGR_DATLEN_24_BIT (0x1 << 1)
|
||||
#define SPI_I2SCFGR_DATLEN_32_BIT (0x2 << 1)
|
||||
#define SPI_I2SCFGR_CHLEN BIT(SPI_I2SCFGR_CHLEN_BIT)
|
||||
#define SPI_I2SCFGR_CHLEN_16_BIT (0x0 << SPI_I2SCFGR_CHLEN_BIT)
|
||||
#define SPI_I2SCFGR_CHLEN_32_BIT (0x1 << SPI_I2SCFGR_CHLEN_BIT)
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
/** SPI device type */
|
||||
typedef struct spi_dev {
|
||||
spi_reg_map *regs; /**< Register map */
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
nvic_irq_num irq_num; /**< NVIC interrupt number */
|
||||
} spi_dev;
|
||||
|
||||
extern spi_dev *SPI1;
|
||||
extern spi_dev *SPI2;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
extern spi_dev *SPI3;
|
||||
#endif
|
||||
#ifdef STM32F2
|
||||
extern spi_dev *SPI4;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SPI Convenience functions
|
||||
*/
|
||||
|
||||
void spi_init(spi_dev *dev);
|
||||
|
||||
void spi_gpio_cfg(uint8 as_master,
|
||||
gpio_dev *nss_dev,
|
||||
uint8 nss_bit,
|
||||
gpio_dev *comm_dev,
|
||||
uint8 sck_bit,
|
||||
uint8 miso_bit,
|
||||
uint8 mosi_bit);
|
||||
|
||||
/**
|
||||
* @brief SPI mode configuration.
|
||||
*
|
||||
* Determines a combination of clock polarity (CPOL), which determines
|
||||
* idle state of the clock line, and clock phase (CPHA), which
|
||||
* determines which clock edge triggers data capture.
|
||||
*/
|
||||
typedef enum spi_mode {
|
||||
SPI_MODE_0, /**< Clock line idles low (0), data capture on first
|
||||
clock transition. */
|
||||
SPI_MODE_1, /**< Clock line idles low (0), data capture on second
|
||||
clock transition */
|
||||
SPI_MODE_2, /**< Clock line idles high (1), data capture on first
|
||||
clock transition. */
|
||||
SPI_MODE_3 /**< Clock line idles high (1), data capture on
|
||||
second clock transition. */
|
||||
} spi_mode;
|
||||
|
||||
/**
|
||||
* @brief SPI baud rate configuration, as a divisor of f_PCLK, the
|
||||
* PCLK clock frequency.
|
||||
*/
|
||||
typedef enum spi_baud_rate {
|
||||
SPI_BAUD_PCLK_DIV_2 = SPI_CR1_BR_PCLK_DIV_2, /**< f_PCLK/2 */
|
||||
SPI_BAUD_PCLK_DIV_4 = SPI_CR1_BR_PCLK_DIV_4, /**< f_PCLK/4 */
|
||||
SPI_BAUD_PCLK_DIV_8 = SPI_CR1_BR_PCLK_DIV_8, /**< f_PCLK/8 */
|
||||
SPI_BAUD_PCLK_DIV_16 = SPI_CR1_BR_PCLK_DIV_16, /**< f_PCLK/16 */
|
||||
SPI_BAUD_PCLK_DIV_32 = SPI_CR1_BR_PCLK_DIV_32, /**< f_PCLK/32 */
|
||||
SPI_BAUD_PCLK_DIV_64 = SPI_CR1_BR_PCLK_DIV_64, /**< f_PCLK/64 */
|
||||
SPI_BAUD_PCLK_DIV_128 = SPI_CR1_BR_PCLK_DIV_128, /**< f_PCLK/128 */
|
||||
SPI_BAUD_PCLK_DIV_256 = SPI_CR1_BR_PCLK_DIV_256, /**< f_PCLK/256 */
|
||||
} spi_baud_rate;
|
||||
|
||||
/**
|
||||
* @brief SPI initialization flags.
|
||||
* @see spi_master_enable()
|
||||
* @see spi_slave_enable()
|
||||
*/
|
||||
typedef enum spi_cfg_flag {
|
||||
SPI_BIDIMODE = SPI_CR1_BIDIMODE, /**< Bidirectional mode enable */
|
||||
SPI_BIDIOE = SPI_CR1_BIDIOE, /**< Output enable in bidirectional
|
||||
mode */
|
||||
SPI_CRCEN = SPI_CR1_CRCEN, /**< Cyclic redundancy check (CRC)
|
||||
enable */
|
||||
SPI_DFF_8_BIT = SPI_CR1_DFF_8_BIT, /**< 8-bit data frame format (this is
|
||||
the default) */
|
||||
SPI_DFF_16_BIT = SPI_CR1_DFF_16_BIT, /**< 16-bit data frame format */
|
||||
SPI_RX_ONLY = SPI_CR1_RXONLY, /**< Receive only */
|
||||
SPI_SW_SLAVE = SPI_CR1_SSM, /**< Software slave management */
|
||||
SPI_SOFT_SS = SPI_CR1_SSI, /**< Software (internal) slave
|
||||
select. This flag only has an
|
||||
effect when used in combination
|
||||
with SPI_SW_SLAVE. */
|
||||
SPI_FRAME_LSB = SPI_CR1_LSBFIRST, /**< LSB-first (little-endian) frame
|
||||
format */
|
||||
SPI_FRAME_MSB = 0, /**< MSB-first (big-endian) frame
|
||||
format (this is the default) */
|
||||
} spi_cfg_flag;
|
||||
|
||||
void spi_master_enable(spi_dev *dev,
|
||||
spi_baud_rate baud,
|
||||
spi_mode mode,
|
||||
uint32 flags);
|
||||
|
||||
void spi_slave_enable(spi_dev *dev,
|
||||
spi_mode mode,
|
||||
uint32 flags);
|
||||
|
||||
uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len);
|
||||
|
||||
void spi_foreach(void (*fn)(spi_dev (*dev)));
|
||||
|
||||
void spi_peripheral_enable(spi_dev *dev);
|
||||
void spi_peripheral_disable(spi_dev *dev);
|
||||
|
||||
void spi_tx_dma_enable(spi_dev *dev);
|
||||
void spi_tx_dma_disable(spi_dev *dev);
|
||||
|
||||
void spi_rx_dma_enable(spi_dev *dev);
|
||||
void spi_rx_dma_disable(spi_dev *dev);
|
||||
|
||||
/**
|
||||
* @brief Determine if a SPI peripheral is enabled.
|
||||
* @param dev SPI device
|
||||
* @return True, if and only if dev's peripheral is enabled.
|
||||
*/
|
||||
static inline uint8 spi_is_enabled(spi_dev *dev) {
|
||||
return dev->regs->CR1 & SPI_CR1_SPE_BIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable all SPI peripherals
|
||||
*/
|
||||
static inline void spi_peripheral_disable_all(void) {
|
||||
spi_foreach(spi_peripheral_disable);
|
||||
}
|
||||
|
||||
/** Available SPI interrupts */
|
||||
typedef enum spi_interrupt {
|
||||
SPI_TXE_INTERRUPT = SPI_CR2_TXEIE, /**< TX buffer empty interrupt */
|
||||
SPI_RXNE_INTERRUPT = SPI_CR2_RXNEIE, /**< RX buffer not empty interrupt */
|
||||
SPI_ERR_INTERRUPT = SPI_CR2_ERRIE /**<
|
||||
* Error interrupt (CRC, overrun,
|
||||
* and mode fault errors for SPI;
|
||||
* underrun, overrun errors for I2S)
|
||||
*/
|
||||
} spi_interrupt;
|
||||
|
||||
/**
|
||||
* @brief Mask for all spi_interrupt values
|
||||
* @see spi_interrupt
|
||||
*/
|
||||
#define SPI_INTERRUPTS_ALL (SPI_TXE_INTERRUPT | \
|
||||
SPI_RXNE_INTERRUPT | \
|
||||
SPI_ERR_INTERRUPT)
|
||||
|
||||
/**
|
||||
* @brief Enable SPI interrupt requests
|
||||
* @param dev SPI device
|
||||
* @param interrupt_flags Bitwise OR of spi_interrupt values to enable
|
||||
* @see spi_interrupt
|
||||
*/
|
||||
static inline void spi_irq_enable(spi_dev *dev, uint32 interrupt_flags) {
|
||||
dev->regs->CR2 |= interrupt_flags;
|
||||
nvic_irq_enable(dev->irq_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable SPI interrupt requests
|
||||
* @param dev SPI device
|
||||
* @param interrupt_flags Bitwise OR of spi_interrupt values to disable
|
||||
* @see spi_interrupt
|
||||
*/
|
||||
static inline void spi_irq_disable(spi_dev *dev, uint32 interrupt_flags) {
|
||||
dev->regs->CR2 &= ~interrupt_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the data frame format flags with which a SPI port is
|
||||
* configured.
|
||||
* @param dev SPI device whose data frame format to get.
|
||||
* @return SPI_DFF_8_BIT, if dev has an 8-bit data frame format.
|
||||
* Otherwise, SPI_DFF_16_BIT.
|
||||
*/
|
||||
static inline spi_cfg_flag spi_dff(spi_dev *dev) {
|
||||
return ((dev->regs->CR1 & SPI_CR1_DFF) == SPI_CR1_DFF_8_BIT ?
|
||||
SPI_DFF_8_BIT :
|
||||
SPI_DFF_16_BIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine whether the device's peripheral receive (RX)
|
||||
* register is empty.
|
||||
* @param dev SPI device
|
||||
* @return true, iff dev's RX register is empty.
|
||||
*/
|
||||
static inline uint8 spi_is_rx_nonempty(spi_dev *dev) {
|
||||
return dev->regs->SR & SPI_SR_RXNE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the contents of the device's peripheral receive
|
||||
* (RX) register.
|
||||
*
|
||||
* You may only call this function when the RX register is nonempty.
|
||||
* Calling this function clears the contents of the RX register.
|
||||
*
|
||||
* @param dev SPI device
|
||||
* @return Contents of dev's peripheral RX register
|
||||
* @see spi_is_rx_reg_nonempty()
|
||||
*/
|
||||
static inline uint16 spi_rx_reg(spi_dev *dev) {
|
||||
return (uint16)dev->regs->DR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine whether the device's peripheral transmit (TX)
|
||||
* register is empty.
|
||||
* @param dev SPI device
|
||||
* @return true, iff dev's TX register is empty.
|
||||
*/
|
||||
static inline uint8 spi_is_tx_empty(spi_dev *dev) {
|
||||
return dev->regs->SR & SPI_SR_TXE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load a value into the device's peripheral transmit (TX) register.
|
||||
*
|
||||
* You may only call this function when the TX register is empty.
|
||||
* Calling this function loads val into the peripheral's TX register.
|
||||
* If the device is properly configured, this will initiate a
|
||||
* transmission, the completion of which will cause the TX register to
|
||||
* be empty again.
|
||||
*
|
||||
* @param dev SPI device
|
||||
* @param val Value to load into the TX register. If the SPI data
|
||||
* frame format is 8 bit, the value must be right-aligned.
|
||||
* @see spi_is_tx_reg_empty()
|
||||
* @see spi_init()
|
||||
* @see spi_master_enable()
|
||||
* @see spi_slave_enable()
|
||||
*/
|
||||
static inline void spi_tx_reg(spi_dev *dev, uint16 val) {
|
||||
dev->regs->DR = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine whether the device's peripheral busy (SPI_SR_BSY)
|
||||
* flag is set.
|
||||
* @param dev SPI device
|
||||
* @return true, iff dev's BSY flag is set.
|
||||
*/
|
||||
static inline uint8 spi_is_busy(spi_dev *dev) {
|
||||
return dev->regs->SR & SPI_SR_BSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2S convenience functions (TODO)
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,220 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 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 stm32.h
|
||||
* @brief STM32 chip-specific definitions
|
||||
*/
|
||||
|
||||
#ifndef _STM32_H_
|
||||
#define _STM32_H_
|
||||
|
||||
/*
|
||||
* User-specific configuration.
|
||||
*
|
||||
* The #defines here depend upon how libmaple is used. Because of the
|
||||
* potential for a mismatch between them and the actual libmaple
|
||||
* usage, you should try to keep their number to an absolute minimum.
|
||||
*/
|
||||
|
||||
#ifdef __DOXYGEN_PREDEFINED_HACK
|
||||
|
||||
/** @brief APB1 clock speed, in Hz. */
|
||||
#define STM32_PCLK1
|
||||
/** @brief APB2 clock speed, in Hz. */
|
||||
#define STM32_PCLK2
|
||||
|
||||
/** Deprecated. Use STM32_PCLK1 instead. */
|
||||
#define PCLK1
|
||||
/** Deprecated. Use STM32_PCLK2 instead. */
|
||||
#define PCLK2
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef STM32_PCLK1
|
||||
#define STM32_PCLK1 36000000U
|
||||
#endif
|
||||
#ifndef PCLK1
|
||||
#define PCLK1 STM32_PCLK1
|
||||
#endif
|
||||
#if PCLK1 != STM32_PCLK1
|
||||
#error "(Deprecated) PCLK1 differs from STM32_PCLK1"
|
||||
#endif
|
||||
|
||||
#ifndef STM32_PCLK2
|
||||
#define STM32_PCLK2 72000000U
|
||||
#endif
|
||||
#ifndef PCLK2
|
||||
#define PCLK2 STM32_PCLK2
|
||||
#endif
|
||||
#if PCLK2 != STM32_PCLK2
|
||||
#error "(Deprecated) PCLK2 differs from STM32_PCLK2"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Density-specific configuration.
|
||||
*/
|
||||
|
||||
#ifdef __DOXYGEN_PREDEFINED_HACK
|
||||
|
||||
/**
|
||||
* @brief Number of interrupts in the NVIC.
|
||||
*
|
||||
* This define is automatically generated whenever the proper
|
||||
* density is defined (currently, this is restricted to defining
|
||||
* one of STM32_MEDIUM_DENSITY and STM32_HIGH_DENSITY).
|
||||
*/
|
||||
#define STM32_NR_INTERRUPTS
|
||||
|
||||
/** Deprecated. Use STM32_NR_INTERRUPTS instead. */
|
||||
#define NR_INTERRUPTS
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef STM32_MEDIUM_DENSITY
|
||||
#define STM32_NR_INTERRUPTS 43
|
||||
#elif defined(STM32_HIGH_DENSITY)
|
||||
#define STM32_NR_INTERRUPTS 60
|
||||
#else
|
||||
#error "No STM32 board type defined!"
|
||||
#endif
|
||||
|
||||
#define NR_INTERRUPTS STM32_NR_INTERRUPTS
|
||||
|
||||
/*
|
||||
* MCU-specific configuration.
|
||||
*/
|
||||
|
||||
#ifdef __DOXYGEN_PREDEFINED_HACK
|
||||
|
||||
/**
|
||||
* Number of GPIO ports.
|
||||
*/
|
||||
#define STM32_NR_GPIO_PORTS
|
||||
|
||||
/**
|
||||
* @brief Multiplier to convert microseconds into loop iterations
|
||||
* in delay_us().
|
||||
*
|
||||
* @see delay_us()
|
||||
*/
|
||||
#define STM32_DELAY_US_MULT
|
||||
|
||||
/**
|
||||
* @brief Pointer to end of built-in SRAM.
|
||||
*
|
||||
* Points to the address which is 1 byte past the last valid
|
||||
* SRAM address.
|
||||
*/
|
||||
#define STM32_SRAM_END
|
||||
|
||||
/** Deprecated. Use STM32_NR_GPIO_PORTS instead. */
|
||||
#define NR_GPIO_PORTS
|
||||
/** Deprecated. Use STM32_DELAY_US_MULT instead. */
|
||||
#define DELAY_US_MULT
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MCU_STM32F103RB)
|
||||
/* e.g., LeafLabs Maple */
|
||||
|
||||
#define STM32_NR_GPIO_PORTS 4
|
||||
#define STM32_DELAY_US_MULT 12
|
||||
#define STM32_SRAM_END ((void*)0x20005000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#elif defined(MCU_STM32F103ZE)
|
||||
/* e.g., LeafLabs Maple Native */
|
||||
|
||||
#define STM32_NR_GPIO_PORTS 7
|
||||
#define STM32_DELAY_US_MULT 12
|
||||
#define STM32_SRAM_END ((void*)0x20010000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#elif defined(MCU_STM32F103CB)
|
||||
/* e.g., LeafLabs Maple Mini */
|
||||
|
||||
/* This STM32_NR_GPIO_PORTS value is not, strictly speaking, true.
|
||||
* But only pins 0 and 1 exist, and they're used for OSC on the
|
||||
* Mini, so we'll live with this for now. */
|
||||
#define STM32_NR_GPIO_PORTS 3
|
||||
#define STM32_DELAY_US_MULT 12
|
||||
#define STM32_SRAM_END ((void*)0x20005000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#elif defined(MCU_STM32F103RE)
|
||||
/* e.g., LeafLabs Maple RET6 edition */
|
||||
|
||||
#define STM32_NR_GPIO_PORTS 4
|
||||
#define STM32_DELAY_US_MULT 12
|
||||
#define STM32_SRAM_END ((void*)0x20010000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#elif defined(MCU_STM32F103VE)
|
||||
/* e.g., LeafLabs Maple Native */
|
||||
|
||||
#define STM32_NR_GPIO_PORTS 5
|
||||
#define STM32_DELAY_US_MULT 12
|
||||
#define STM32_SRAM_END ((void*)0x20010000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#elif defined(MCU_STM32F205VE)
|
||||
#define STM32_TICKS_PER_US 120
|
||||
#define STM32_NR_GPIO_PORTS 5
|
||||
#define STM32_DELAY_US_MULT (STM32_TICKS_PER_US/3)
|
||||
#define STM32_SRAM_END ((void*)0x20010000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#elif defined(MCU_STM32F406VG)
|
||||
#define STM32_TICKS_PER_US 168
|
||||
#define STM32_NR_GPIO_PORTS 5
|
||||
#define STM32_DELAY_US_MULT (STM32_TICKS_PER_US/3)
|
||||
#define STM32_SRAM_END ((void*)0x20010000)
|
||||
//#define STM32_SRAM_END ((void*)0x20030000)
|
||||
|
||||
#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS
|
||||
#define DELAY_US_MULT STM32_DELAY_US_MULT
|
||||
|
||||
#else
|
||||
|
||||
#error "No MCU type specified. Add something like -DMCU_STM32F103RB " \
|
||||
"to your compiler arguments (probably in a Makefile)."
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _STM32_H_ */
|
|
@ -0,0 +1,167 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file syscalls.c
|
||||
* @brief Low level system routines used by Newlib for basic I/O and
|
||||
* memory allocation.
|
||||
*/
|
||||
|
||||
#include "libmaple.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then
|
||||
* assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by
|
||||
* the linker */
|
||||
#ifndef CONFIG_HEAP_START
|
||||
extern char _lm_heap_start;
|
||||
#define CONFIG_HEAP_START ((caddr_t)&_lm_heap_start)
|
||||
#endif
|
||||
#ifndef CONFIG_HEAP_END
|
||||
extern char _lm_heap_end;
|
||||
#define CONFIG_HEAP_END ((caddr_t)&_lm_heap_end)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* _sbrk -- Increment the program break.
|
||||
*
|
||||
* Get incr bytes more RAM (for use by the heap). malloc() and
|
||||
* friends call this function behind the scenes.
|
||||
*/
|
||||
caddr_t _sbrk(int incr) {
|
||||
static caddr_t pbreak = NULL; /* current program break */
|
||||
caddr_t ret;
|
||||
|
||||
if (pbreak == NULL) {
|
||||
pbreak = CONFIG_HEAP_START;
|
||||
}
|
||||
|
||||
if ((CONFIG_HEAP_END - pbreak < incr) ||
|
||||
(pbreak - CONFIG_HEAP_START < -incr)) {
|
||||
errno = ENOMEM;
|
||||
return (caddr_t)-1;
|
||||
}
|
||||
|
||||
ret = pbreak;
|
||||
pbreak += incr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _open(const char *path, int flags, ...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _close(int fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _fstat(int fd, struct stat *st) {
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int fd) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int isatty(int fd) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int fd, off_t pos, int whence) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char getch(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int _read(int fd, char *buf, size_t cnt) {
|
||||
*buf = getch();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void putch(unsigned char c) {
|
||||
}
|
||||
|
||||
void cgets(char *s, int bufsize) {
|
||||
char *p;
|
||||
int c;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bufsize; i++) {
|
||||
*(s+i) = 0;
|
||||
}
|
||||
// memset(s, 0, bufsize);
|
||||
|
||||
p = s;
|
||||
|
||||
for (p = s; p < s + bufsize-1;) {
|
||||
c = getch();
|
||||
switch (c) {
|
||||
case '\r' :
|
||||
case '\n' :
|
||||
putch('\r');
|
||||
putch('\n');
|
||||
*p = '\n';
|
||||
return;
|
||||
|
||||
case '\b' :
|
||||
if (p > s) {
|
||||
*p-- = 0;
|
||||
putch('\b');
|
||||
putch(' ');
|
||||
putch('\b');
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
putch(c);
|
||||
*p++ = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int _write(int fd, const char *buf, size_t cnt) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
putch(buf[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Override fgets() in newlib with a version that does line editing */
|
||||
char *fgets(char *s, int bufsize, void *f) {
|
||||
cgets(s, bufsize);
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file systick.c
|
||||
* @brief System timer interrupt handler and initialization routines
|
||||
*/
|
||||
|
||||
#include "systick.h"
|
||||
#include "nvic.h"
|
||||
volatile uint32 systick_uptime_millis;
|
||||
static void (*systick_user_callback)(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize and enable SysTick.
|
||||
*
|
||||
* Clocks the system timer with the core clock, turns it on, and
|
||||
* enables interrupts.
|
||||
*
|
||||
* @param reload_val Appropriate reload counter to tick every 1 ms.
|
||||
*/
|
||||
void systick_init(uint32 reload_val) {
|
||||
SYSTICK_BASE->RVR = reload_val;
|
||||
systick_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clock the system timer with the core clock, but don't turn it
|
||||
* on or enable interrupt.
|
||||
*/
|
||||
void systick_disable() {
|
||||
SYSTICK_BASE->CSR = SYSTICK_CSR_CLKSOURCE_CORE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clock the system timer with the core clock and turn it on;
|
||||
* interrupt every 1 ms, for systick_timer_millis.
|
||||
*/
|
||||
void systick_enable() {
|
||||
/* re-enables init registers without changing reload val */
|
||||
SYSTICK_BASE->CSR = (SYSTICK_CSR_CLKSOURCE_CORE |
|
||||
SYSTICK_CSR_ENABLE |
|
||||
SYSTICK_CSR_TICKINT_PEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a callback to be called from the SysTick exception handler.
|
||||
*
|
||||
* To detach a callback, call this function again with a null argument.
|
||||
*/
|
||||
void systick_attach_callback(void (*callback)(void)) {
|
||||
systick_user_callback = callback;
|
||||
}
|
||||
|
||||
/*
|
||||
* SysTick ISR
|
||||
*/
|
||||
|
||||
void __exc_systick(void) {
|
||||
nvic_globalirq_disable();
|
||||
systick_check_underflow();
|
||||
systick_uptime_millis++;
|
||||
nvic_globalirq_enable();
|
||||
|
||||
if (systick_user_callback) {
|
||||
systick_user_callback();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file systick.h
|
||||
*
|
||||
* @brief Various system timer definitions
|
||||
*/
|
||||
|
||||
#ifndef _SYSTICK_H_
|
||||
#define _SYSTICK_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** SysTick register map type */
|
||||
typedef struct systick_reg_map {
|
||||
__io uint32 CSR; /**< Control and status register */
|
||||
__io uint32 RVR; /**< Reload value register */
|
||||
__io uint32 CNT; /**< Current value register ("count") */
|
||||
__io uint32 CVR; /**< Calibration value register */
|
||||
} systick_reg_map;
|
||||
|
||||
/** SysTick register map base pointer */
|
||||
#define SYSTICK_BASE ((struct systick_reg_map*)0xE000E010)
|
||||
|
||||
/*
|
||||
* Register bit definitions.
|
||||
*/
|
||||
|
||||
/* Control and status register */
|
||||
|
||||
#define SYSTICK_CSR_COUNTFLAG BIT(16)
|
||||
#define SYSTICK_CSR_CLKSOURCE BIT(2)
|
||||
#define SYSTICK_CSR_CLKSOURCE_EXTERNAL 0
|
||||
#define SYSTICK_CSR_CLKSOURCE_CORE BIT(2)
|
||||
#define SYSTICK_CSR_TICKINT BIT(1)
|
||||
#define SYSTICK_CSR_TICKINT_PEND BIT(1)
|
||||
#define SYSTICK_CSR_TICKINT_NO_PEND 0
|
||||
#define SYSTICK_CSR_ENABLE BIT(0)
|
||||
#define SYSTICK_CSR_ENABLE_MULTISHOT BIT(0)
|
||||
#define SYSTICK_CSR_ENABLE_DISABLED 0
|
||||
|
||||
/* Calibration value register */
|
||||
|
||||
#define SYSTICK_CVR_NOREF BIT(31)
|
||||
#define SYSTICK_CVR_SKEW BIT(30)
|
||||
#define SYSTICK_CVR_TENMS 0xFFFFFF
|
||||
|
||||
/** System elapsed time, in milliseconds */
|
||||
extern volatile uint32 systick_uptime_millis;
|
||||
|
||||
/**
|
||||
* @brief Returns the system uptime, in milliseconds.
|
||||
*/
|
||||
static inline uint32 systick_uptime(void) {
|
||||
return systick_uptime_millis;
|
||||
}
|
||||
|
||||
|
||||
void systick_init(uint32 reload_val);
|
||||
void systick_disable();
|
||||
void systick_enable();
|
||||
|
||||
/**
|
||||
* @brief Returns the current value of the SysTick counter.
|
||||
*/
|
||||
static inline uint32 systick_get_count(void) {
|
||||
return SYSTICK_BASE->CNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for underflow.
|
||||
*
|
||||
* This function returns 1 if the SysTick timer has counted to 0 since
|
||||
* the last time it was called. However, any reads of any part of the
|
||||
* SysTick Control and Status Register SYSTICK_BASE->CSR will
|
||||
* interfere with this functionality. See the ARM Cortex M3 Technical
|
||||
* Reference Manual for more details (e.g. Table 8-3 in revision r1p1).
|
||||
*/
|
||||
static inline uint32 systick_check_underflow(void) {
|
||||
return SYSTICK_BASE->CSR & SYSTICK_CSR_COUNTFLAG;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,480 @@
|
|||
/******************************************************************************
|
||||
* 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 timer.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief New-style timer interface
|
||||
*/
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
/* Just like the corresponding DIER bits:
|
||||
* [0] = Update handler;
|
||||
* [1,2,3,4] = capture/compare 1,2,3,4 handlers, respectively;
|
||||
* [5] = COM;
|
||||
* [6] = TRG;
|
||||
* [7] = BRK. */
|
||||
#define NR_ADV_HANDLERS 8
|
||||
/* Update, capture/compare 1,2,3,4; <junk>; trigger. */
|
||||
#define NR_GEN_HANDLERS 7
|
||||
/* Update only. */
|
||||
#define NR_BAS_HANDLERS 1
|
||||
|
||||
static timer_dev timer1 = {
|
||||
.regs = { .adv = TIMER1_BASE },
|
||||
.clk_id = RCC_TIMER1,
|
||||
.type = TIMER_ADVANCED,
|
||||
.handlers = { [NR_ADV_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 1 device (advanced) */
|
||||
timer_dev *TIMER1 = &timer1;
|
||||
|
||||
static timer_dev timer2 = {
|
||||
.regs = { .gen = TIMER2_BASE },
|
||||
.clk_id = RCC_TIMER2,
|
||||
.type = TIMER_GENERAL,
|
||||
.handlers = { [NR_GEN_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 2 device (general-purpose) */
|
||||
timer_dev *TIMER2 = &timer2;
|
||||
|
||||
static timer_dev timer3 = {
|
||||
.regs = { .gen = TIMER3_BASE },
|
||||
.clk_id = RCC_TIMER3,
|
||||
.type = TIMER_GENERAL,
|
||||
.handlers = { [NR_GEN_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 3 device (general-purpose) */
|
||||
timer_dev *TIMER3 = &timer3;
|
||||
|
||||
static timer_dev timer4 = {
|
||||
.regs = { .gen = TIMER4_BASE },
|
||||
.clk_id = RCC_TIMER4,
|
||||
.type = TIMER_GENERAL,
|
||||
.handlers = { [NR_GEN_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 4 device (general-purpose) */
|
||||
timer_dev *TIMER4 = &timer4;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
static timer_dev timer5 = {
|
||||
.regs = { .gen = TIMER5_BASE },
|
||||
.clk_id = RCC_TIMER5,
|
||||
.type = TIMER_GENERAL,
|
||||
.handlers = { [NR_GEN_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 5 device (general-purpose) */
|
||||
timer_dev *TIMER5 = &timer5;
|
||||
|
||||
static timer_dev timer6 = {
|
||||
.regs = { .bas = TIMER6_BASE },
|
||||
.clk_id = RCC_TIMER6,
|
||||
.type = TIMER_BASIC,
|
||||
.handlers = { [NR_BAS_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 6 device (basic) */
|
||||
timer_dev *TIMER6 = &timer6;
|
||||
|
||||
static timer_dev timer7 = {
|
||||
.regs = { .bas = TIMER7_BASE },
|
||||
.clk_id = RCC_TIMER7,
|
||||
.type = TIMER_BASIC,
|
||||
.handlers = { [NR_BAS_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 7 device (basic) */
|
||||
timer_dev *TIMER7 = &timer7;
|
||||
|
||||
static timer_dev timer8 = {
|
||||
.regs = { .adv = TIMER8_BASE },
|
||||
.clk_id = RCC_TIMER8,
|
||||
.type = TIMER_ADVANCED,
|
||||
.handlers = { [NR_ADV_HANDLERS - 1] = 0 },
|
||||
};
|
||||
/** Timer 8 device (advanced) */
|
||||
timer_dev *TIMER8 = &timer8;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
static void disable_channel(timer_dev *dev, uint8 channel);
|
||||
static void pwm_mode(timer_dev *dev, uint8 channel);
|
||||
static void output_compare_mode(timer_dev *dev, uint8 channel);
|
||||
|
||||
static inline void enable_irq(timer_dev *dev, uint8 interrupt);
|
||||
|
||||
/**
|
||||
* Initialize a timer, and reset its register map.
|
||||
* @param dev Timer to initialize
|
||||
*/
|
||||
void timer_init(timer_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a timer.
|
||||
*
|
||||
* The timer will stop counting, all DMA requests and interrupts will
|
||||
* be disabled, and no state changes will be output.
|
||||
*
|
||||
* @param dev Timer to disable.
|
||||
*/
|
||||
void timer_disable(timer_dev *dev) {
|
||||
(dev->regs).bas->CR1 = 0;
|
||||
(dev->regs).bas->DIER = 0;
|
||||
switch (dev->type) {
|
||||
case TIMER_ADVANCED: /* fall-through */
|
||||
case TIMER_GENERAL:
|
||||
(dev->regs).gen->CCER = 0;
|
||||
break;
|
||||
case TIMER_BASIC:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mode of an individual timer channel.
|
||||
*
|
||||
* Note that not all timers can be configured in every mode. For
|
||||
* example, basic timers cannot be configured to output compare mode.
|
||||
* Be sure to use a timer which is appropriate for the mode you want.
|
||||
*
|
||||
* @param dev Timer whose channel mode to set
|
||||
* @param channel Relevant channel
|
||||
* @param mode New timer mode for channel
|
||||
*/
|
||||
void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) {
|
||||
ASSERT_FAULT(channel > 0 && channel <= 4);
|
||||
|
||||
/* TODO decide about the basic timers */
|
||||
ASSERT(dev->type != TIMER_BASIC);
|
||||
if (dev->type == TIMER_BASIC)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case TIMER_DISABLED:
|
||||
disable_channel(dev, channel);
|
||||
break;
|
||||
case TIMER_PWM:
|
||||
pwm_mode(dev, channel);
|
||||
break;
|
||||
case TIMER_OUTPUT_COMPARE:
|
||||
output_compare_mode(dev, channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call a function on timer devices.
|
||||
* @param fn Function to call on each timer device.
|
||||
*/
|
||||
void timer_foreach(void (*fn)(timer_dev*)) {
|
||||
fn(TIMER1);
|
||||
fn(TIMER2);
|
||||
fn(TIMER3);
|
||||
fn(TIMER4);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
fn(TIMER5);
|
||||
fn(TIMER6);
|
||||
fn(TIMER7);
|
||||
fn(TIMER8);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a timer interrupt.
|
||||
* @param dev Timer device
|
||||
* @param interrupt Interrupt number to attach to; this may be any
|
||||
* timer_interrupt_id or timer_channel value appropriate
|
||||
* for the timer.
|
||||
* @param handler Handler to attach to the given interrupt.
|
||||
* @see timer_interrupt_id
|
||||
* @see timer_channel
|
||||
*/
|
||||
void timer_attach_interrupt(timer_dev *dev,
|
||||
uint8 interrupt,
|
||||
voidFuncPtr handler) {
|
||||
dev->handlers[interrupt] = handler;
|
||||
timer_enable_irq(dev, interrupt);
|
||||
enable_irq(dev, interrupt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach a timer interrupt.
|
||||
* @param dev Timer device
|
||||
* @param interrupt Interrupt number to detach; this may be any
|
||||
* timer_interrupt_id or timer_channel value appropriate
|
||||
* for the timer.
|
||||
* @see timer_interrupt_id
|
||||
* @see timer_channel
|
||||
*/
|
||||
void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) {
|
||||
timer_disable_irq(dev, interrupt);
|
||||
dev->handlers[interrupt] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handlers
|
||||
*/
|
||||
|
||||
static inline void dispatch_adv_brk(timer_dev *dev);
|
||||
static inline void dispatch_adv_up(timer_dev *dev);
|
||||
static inline void dispatch_adv_trg_com(timer_dev *dev);
|
||||
static inline void dispatch_adv_cc(timer_dev *dev);
|
||||
static inline void dispatch_general(timer_dev *dev);
|
||||
static inline void dispatch_basic(timer_dev *dev);
|
||||
|
||||
void __irq_tim1_brk(void) {
|
||||
dispatch_adv_brk(TIMER1);
|
||||
}
|
||||
|
||||
void __irq_tim1_up(void) {
|
||||
dispatch_adv_up(TIMER1);
|
||||
}
|
||||
|
||||
void __irq_tim1_trg_com(void) {
|
||||
dispatch_adv_trg_com(TIMER1);
|
||||
}
|
||||
|
||||
void __irq_tim1_cc(void) {
|
||||
dispatch_adv_cc(TIMER1);
|
||||
}
|
||||
|
||||
void __irq_tim2(void) {
|
||||
dispatch_general(TIMER2);
|
||||
}
|
||||
|
||||
void __irq_tim3(void) {
|
||||
dispatch_general(TIMER3);
|
||||
}
|
||||
|
||||
void __irq_tim4(void) {
|
||||
dispatch_general(TIMER4);
|
||||
}
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
|
||||
void __irq_tim5(void) {
|
||||
dispatch_general(TIMER5);
|
||||
}
|
||||
|
||||
void __irq_tim6(void) {
|
||||
dispatch_basic(TIMER6);
|
||||
}
|
||||
|
||||
void __irq_tim7(void) {
|
||||
dispatch_basic(TIMER7);
|
||||
}
|
||||
|
||||
void __irq_tim8_brk(void) {
|
||||
dispatch_adv_brk(TIMER8);
|
||||
}
|
||||
|
||||
void __irq_tim8_up(void) {
|
||||
dispatch_adv_up(TIMER8);
|
||||
}
|
||||
|
||||
void __irq_tim8_trg_com(void) {
|
||||
dispatch_adv_trg_com(TIMER8);
|
||||
}
|
||||
|
||||
void __irq_tim8_cc(void) {
|
||||
dispatch_adv_cc(TIMER8);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note: the following dispatch routines make use of the fact that
|
||||
* DIER interrupt enable bits and SR interrupt flags have common bit
|
||||
* positions. Thus, ANDing DIER and SR lets us check if an interrupt
|
||||
* is enabled and if it has occurred simultaneously.
|
||||
*/
|
||||
|
||||
/* A special-case dispatch routine for single-interrupt NVIC lines.
|
||||
* This function assumes that the interrupt corresponding to `iid' has
|
||||
* in fact occurred (i.e., it doesn't check DIER & SR). */
|
||||
static inline void dispatch_single_irq(timer_dev *dev,
|
||||
timer_interrupt_id iid,
|
||||
uint32 irq_mask) {
|
||||
timer_bas_reg_map *regs = (dev->regs).bas;
|
||||
void (*handler)(void) = dev->handlers[iid];
|
||||
if (handler) {
|
||||
handler();
|
||||
regs->SR &= ~irq_mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* For dispatch routines which service multiple interrupts. */
|
||||
#define handle_irq(dier_sr, irq_mask, handlers, iid, handled_irq) do { \
|
||||
if ((dier_sr) & (irq_mask)) { \
|
||||
void (*__handler)(void) = (handlers)[iid]; \
|
||||
if (__handler) { \
|
||||
__handler(); \
|
||||
handled_irq |= (irq_mask); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline void dispatch_adv_brk(timer_dev *dev) {
|
||||
dispatch_single_irq(dev, TIMER_BREAK_INTERRUPT, TIMER_SR_BIF);
|
||||
}
|
||||
|
||||
static inline void dispatch_adv_up(timer_dev *dev) {
|
||||
dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF);
|
||||
}
|
||||
|
||||
static inline void dispatch_adv_trg_com(timer_dev *dev) {
|
||||
timer_adv_reg_map *regs = (dev->regs).adv;
|
||||
uint32 dsr = regs->DIER & regs->SR;
|
||||
void (**hs)(void) = dev->handlers;
|
||||
uint32 handled = 0; /* Logical OR of SR interrupt flags we end up
|
||||
* handling. We clear these. User handlers
|
||||
* must clear overcapture flags, to avoid
|
||||
* wasting time in output mode. */
|
||||
|
||||
handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_COMIF, hs, TIMER_COM_INTERRUPT, handled);
|
||||
|
||||
regs->SR &= ~handled;
|
||||
}
|
||||
|
||||
static inline void dispatch_adv_cc(timer_dev *dev) {
|
||||
timer_adv_reg_map *regs = (dev->regs).adv;
|
||||
uint32 dsr = regs->DIER & regs->SR;
|
||||
void (**hs)(void) = dev->handlers;
|
||||
uint32 handled = 0;
|
||||
|
||||
handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled);
|
||||
|
||||
regs->SR &= ~handled;
|
||||
}
|
||||
|
||||
static inline void dispatch_general(timer_dev *dev) {
|
||||
timer_gen_reg_map *regs = (dev->regs).gen;
|
||||
uint32 dsr = regs->DIER & regs->SR;
|
||||
void (**hs)(void) = dev->handlers;
|
||||
uint32 handled = 0;
|
||||
|
||||
handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled);
|
||||
handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled);
|
||||
|
||||
regs->SR &= ~handled;
|
||||
}
|
||||
|
||||
static inline void dispatch_basic(timer_dev *dev) {
|
||||
dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
static void disable_channel(timer_dev *dev, uint8 channel) {
|
||||
timer_detach_interrupt(dev, channel);
|
||||
timer_cc_disable(dev, channel);
|
||||
}
|
||||
|
||||
static void pwm_mode(timer_dev *dev, uint8 channel) {
|
||||
timer_disable_irq(dev, channel);
|
||||
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE);
|
||||
timer_cc_enable(dev, channel);
|
||||
}
|
||||
|
||||
static void output_compare_mode(timer_dev *dev, uint8 channel) {
|
||||
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_ACTIVE_ON_MATCH, 0);
|
||||
timer_cc_enable(dev, channel);
|
||||
}
|
||||
|
||||
static void enable_advanced_irq(timer_dev *dev, timer_interrupt_id id);
|
||||
static void enable_nonmuxed_irq(timer_dev *dev);
|
||||
|
||||
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) {
|
||||
if (dev->type == TIMER_ADVANCED) {
|
||||
enable_advanced_irq(dev, iid);
|
||||
} else {
|
||||
enable_nonmuxed_irq(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_advanced_irq(timer_dev *dev, timer_interrupt_id id) {
|
||||
uint8 is_timer1 = dev->clk_id == RCC_TIMER1;
|
||||
|
||||
switch (id) {
|
||||
case TIMER_UPDATE_INTERRUPT:
|
||||
nvic_irq_enable(is_timer1 ? NVIC_TIMER1_UP : NVIC_TIMER8_UP);
|
||||
break;
|
||||
case TIMER_CC1_INTERRUPT:
|
||||
case TIMER_CC2_INTERRUPT:
|
||||
case TIMER_CC3_INTERRUPT:
|
||||
case TIMER_CC4_INTERRUPT:
|
||||
nvic_irq_enable(is_timer1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC);
|
||||
break;
|
||||
case TIMER_COM_INTERRUPT:
|
||||
case TIMER_TRG_INTERRUPT:
|
||||
nvic_irq_enable(is_timer1 ? NVIC_TIMER1_TRG_COM : NVIC_TIMER8_TRG_COM);
|
||||
break;
|
||||
case TIMER_BREAK_INTERRUPT:
|
||||
nvic_irq_enable(is_timer1 ? NVIC_TIMER1_BRK : NVIC_TIMER8_BRK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_nonmuxed_irq(timer_dev *dev) {
|
||||
switch (dev->clk_id) {
|
||||
case RCC_TIMER2:
|
||||
nvic_irq_enable(NVIC_TIMER2);
|
||||
break;
|
||||
case RCC_TIMER3:
|
||||
nvic_irq_enable(NVIC_TIMER3);
|
||||
break;
|
||||
case RCC_TIMER4:
|
||||
nvic_irq_enable(NVIC_TIMER4);
|
||||
break;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
case RCC_TIMER5:
|
||||
nvic_irq_enable(NVIC_TIMER5);
|
||||
break;
|
||||
case RCC_TIMER6:
|
||||
nvic_irq_enable(NVIC_TIMER6);
|
||||
break;
|
||||
case RCC_TIMER7:
|
||||
nvic_irq_enable(NVIC_TIMER7);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ASSERT_FAULT(0);
|
||||
break;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,294 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file usart.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Perry Hung <perry@leaflabs.com>
|
||||
* @brief USART control routines
|
||||
*/
|
||||
|
||||
#include "usart.h"
|
||||
#define USART_TX_IRQ
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static usart_dev usart1 = {
|
||||
.regs = USART1_BASE,
|
||||
.max_baud = 4500000UL,
|
||||
.clk_id = RCC_USART1,
|
||||
.irq_num = NVIC_USART1
|
||||
};
|
||||
/** USART1 device */
|
||||
usart_dev *USART1 = &usart1;
|
||||
|
||||
static usart_dev usart2 = {
|
||||
.regs = USART2_BASE,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_USART2,
|
||||
.irq_num = NVIC_USART2
|
||||
};
|
||||
/** USART2 device */
|
||||
usart_dev *USART2 = &usart2;
|
||||
|
||||
static usart_dev usart3 = {
|
||||
.regs = USART3_BASE,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_USART3,
|
||||
.irq_num = NVIC_USART3
|
||||
};
|
||||
/** USART3 device */
|
||||
usart_dev *USART3 = &usart3;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
static usart_dev uart4 = {
|
||||
.regs = UART4_BASE,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_UART4,
|
||||
.irq_num = NVIC_UART4
|
||||
};
|
||||
/** UART4 device */
|
||||
usart_dev *UART4 = &uart4;
|
||||
|
||||
static usart_dev uart5 = {
|
||||
.regs = UART5_BASE,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_UART5,
|
||||
.irq_num = NVIC_UART5
|
||||
};
|
||||
/** UART5 device */
|
||||
usart_dev *UART5 = &uart5;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize a serial port.
|
||||
* @param dev Serial port to be initialized
|
||||
*/
|
||||
void usart_init(usart_dev *dev) {
|
||||
rb_init(&dev->rbRX, USART_RX_BUF_SIZE, dev->rx_buf);
|
||||
rb_init(&dev->rbTX, USART_TX_BUF_SIZE, dev->tx_buf);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
nvic_irq_enable(dev->irq_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure a serial port's baud rate.
|
||||
*
|
||||
* @param dev Serial port to be configured
|
||||
* @param clock_speed Clock speed, in megahertz.
|
||||
* @param baud Baud rate for transmit/receive.
|
||||
*/
|
||||
void usart_set_baud_rate(usart_dev *dev, uint32 baud) {
|
||||
uint32 integer_part;
|
||||
uint32 fractional_part;
|
||||
uint32 tmp;
|
||||
|
||||
uint32 clock_speed = rcc_dev_clk_speed(dev->clk_id);
|
||||
|
||||
/* See ST RM0008 for the details on configuring the baud rate register */
|
||||
integer_part = (25 * clock_speed) / (4 * baud);
|
||||
tmp = (integer_part / 100) << 4;
|
||||
fractional_part = integer_part - (100 * (tmp >> 4));
|
||||
tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F);
|
||||
|
||||
dev->regs->BRR = (uint16)tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a serial port.
|
||||
*
|
||||
* USART is enabled in single buffer transmission mode, multibuffer
|
||||
* receiver mode, 8n1.
|
||||
*
|
||||
* Serial port must have a baud rate configured to work properly.
|
||||
*
|
||||
* @param dev Serial port to enable.
|
||||
* @see usart_set_baud_rate()
|
||||
*/
|
||||
void usart_enable(usart_dev *dev) {
|
||||
usart_reg_map *regs = dev->regs;
|
||||
regs->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
|
||||
regs->CR1 |= USART_CR1_UE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable serial port tx interrupt.
|
||||
*
|
||||
* @param dev Serial port.
|
||||
*/
|
||||
void usart_tx_irq_enable(usart_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR1, USART_CR1_TXEIE_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable serial port tx interrupt.
|
||||
*
|
||||
* @param dev Serial port.
|
||||
*/
|
||||
void usart_tx_irq_disable(usart_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR1, USART_CR1_TXEIE_BIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn off a serial port.
|
||||
* @param dev Serial port to be disabled
|
||||
*/
|
||||
void usart_disable(usart_dev *dev) {
|
||||
/* FIXME this misbehaves if you try to use PWM on TX afterwards */
|
||||
usart_reg_map *regs = dev->regs;
|
||||
|
||||
// flush output buffer
|
||||
while(usart_data_pending(dev) > 0)
|
||||
;
|
||||
|
||||
/* TC bit must be high before disabling the USART */
|
||||
while((regs->CR1 & USART_CR1_UE) && !(regs->SR & USART_SR_TC))
|
||||
;
|
||||
|
||||
/* Disable UE */
|
||||
regs->CR1 &= ~USART_CR1_UE;
|
||||
|
||||
/* Clean up buffer */
|
||||
usart_reset_rx(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call a function on each USART.
|
||||
* @param fn Function to call.
|
||||
*/
|
||||
void usart_foreach(void (*fn)(usart_dev*)) {
|
||||
fn(USART1);
|
||||
fn(USART2);
|
||||
fn(USART3);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
fn(UART4);
|
||||
fn(UART5);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Nonblocking USART transmit
|
||||
* @param dev Serial port to transmit over
|
||||
* @param buf Buffer to transmit
|
||||
* @param len Maximum number of bytes to transmit
|
||||
* @return Number of bytes transmitted
|
||||
*/
|
||||
uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len) {
|
||||
uint32 txed = 0;
|
||||
#ifdef USART_TX_IRQ
|
||||
while (txed < len && rb_safe_insert(&dev->rbTX, buf[txed])) {
|
||||
usart_tx_irq_enable(dev);
|
||||
txed++;
|
||||
}
|
||||
|
||||
#else
|
||||
usart_reg_map *regs = dev->regs;
|
||||
while ((regs->SR & USART_SR_TXE) && (txed < len)) {
|
||||
regs->DR = buf[txed++];
|
||||
}
|
||||
#endif
|
||||
|
||||
return txed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an unsigned integer to the specified serial port in
|
||||
* decimal format.
|
||||
*
|
||||
* This function blocks until the integer's digits have been
|
||||
* completely transmitted.
|
||||
*
|
||||
* @param dev Serial port to send on
|
||||
* @param val Number to print
|
||||
*/
|
||||
void usart_putudec(usart_dev *dev, uint32 val) {
|
||||
char digits[12];
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
digits[i++] = val % 10 + '0';
|
||||
val /= 10;
|
||||
} while (val > 0);
|
||||
|
||||
while (--i >= 0) {
|
||||
usart_putc(dev, digits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handlers.
|
||||
*/
|
||||
static inline void usart_irq(usart_dev *dev) {
|
||||
volatile int sr = dev->regs->SR;
|
||||
if(sr & USART_SR_RXNE) {
|
||||
#ifdef USART_SAFE_INSERT
|
||||
/* If the buffer is full and the user defines USART_SAFE_INSERT,
|
||||
* ignore new bytes. */
|
||||
rb_safe_insert(&dev->rbRX, (uint8)dev->regs->DR);
|
||||
#else
|
||||
/* By default, push bytes around in the ring buffer. */
|
||||
rb_push_insert(&dev->rbRX, (uint8)dev->regs->DR);
|
||||
#endif
|
||||
|
||||
#ifdef USART_TX_IRQ
|
||||
} else if(sr & USART_SR_TXE) {
|
||||
if(rb_full_count(&dev->rbTX) > 0) {
|
||||
dev->regs->DR = rb_remove(&dev->rbTX);
|
||||
} else {
|
||||
usart_tx_irq_disable(dev); // disable tx irq
|
||||
// nops needed to deactivate the irq before irq handler is left
|
||||
asm volatile("nop");
|
||||
asm volatile("nop");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void __irq_usart1(void) {
|
||||
usart_irq(USART1);
|
||||
}
|
||||
|
||||
void __irq_usart2(void) {
|
||||
usart_irq(USART2);
|
||||
}
|
||||
|
||||
void __irq_usart3(void) {
|
||||
usart_irq(USART3);
|
||||
}
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
void __irq_uart4(void) {
|
||||
usart_irq(UART4);
|
||||
}
|
||||
|
||||
void __irq_uart5(void) {
|
||||
usart_irq(UART5);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,356 @@
|
|||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file usart.h
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Perry Hung <perry@leaflabs.com>
|
||||
* @brief USART definitions and prototypes
|
||||
*/
|
||||
|
||||
#ifndef _USART_H_
|
||||
#define _USART_H_
|
||||
|
||||
#include "libmaple_types.h"
|
||||
#include "util.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
#include "ring_buffer.h"
|
||||
#include "bitband.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register maps and devices
|
||||
*/
|
||||
|
||||
/** USART register map type */
|
||||
typedef struct usart_reg_map {
|
||||
__io uint32 SR; /**< Status register */
|
||||
__io uint32 DR; /**< Data register */
|
||||
__io uint32 BRR; /**< Baud rate register */
|
||||
__io uint32 CR1; /**< Control register 1 */
|
||||
__io uint32 CR2; /**< Control register 2 */
|
||||
__io uint32 CR3; /**< Control register 3 */
|
||||
__io uint32 GTPR; /**< Guard time and prescaler register */
|
||||
} usart_reg_map;
|
||||
|
||||
/** USART1 register map base pointer */
|
||||
#ifdef STM32F2
|
||||
#define USART1_BASE ((struct usart_reg_map*)0x40011000)
|
||||
#else
|
||||
#define USART1_BASE ((struct usart_reg_map*)0x40013800)
|
||||
#endif
|
||||
/** USART2 register map base pointer */
|
||||
#define USART2_BASE ((struct usart_reg_map*)0x40004400)
|
||||
/** USART3 register map base pointer */
|
||||
#define USART3_BASE ((struct usart_reg_map*)0x40004800)
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
/** UART4 register map base pointer */
|
||||
#define UART4_BASE ((struct usart_reg_map*)0x40004C00)
|
||||
/** UART5 register map base pointer */
|
||||
#define UART5_BASE ((struct usart_reg_map*)0x40005000)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register bit definitions
|
||||
*/
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define USART_SR_CTS_BIT 9
|
||||
#define USART_SR_LBD_BIT 8
|
||||
#define USART_SR_TXE_BIT 7
|
||||
#define USART_SR_TC_BIT 6
|
||||
#define USART_SR_RXNE_BIT 5
|
||||
#define USART_SR_IDLE_BIT 4
|
||||
#define USART_SR_ORE_BIT 3
|
||||
#define USART_SR_NE_BIT 2
|
||||
#define USART_SR_FE_BIT 1
|
||||
#define USART_SR_PE_BIT 0
|
||||
|
||||
#define USART_SR_CTS BIT(USART_SR_CTS_BIT)
|
||||
#define USART_SR_LBD BIT(USART_SR_LBD_BIT)
|
||||
#define USART_SR_TXE BIT(USART_SR_TXE_BIT)
|
||||
#define USART_SR_TC BIT(USART_SR_TC_BIT)
|
||||
#define USART_SR_RXNE BIT(USART_SR_RXNE_BIT)
|
||||
#define USART_SR_IDLE BIT(USART_SR_IDLE_BIT)
|
||||
#define USART_SR_ORE BIT(USART_SR_ORE_BIT)
|
||||
#define USART_SR_NE BIT(USART_SR_NE_BIT)
|
||||
#define USART_SR_FE BIT(USART_SR_FE_BIT)
|
||||
#define USART_SR_PE BIT(USART_SR_PE_BIT)
|
||||
|
||||
/* Data register */
|
||||
|
||||
#define USART_DR_DR 0xFF
|
||||
|
||||
/* Baud rate register */
|
||||
|
||||
#define USART_BRR_DIV_MANTISSA (0xFFF << 4)
|
||||
#define USART_BRR_DIV_FRACTION 0xF
|
||||
|
||||
/* Control register 1 */
|
||||
|
||||
#define USART_CR1_UE_BIT 13
|
||||
#define USART_CR1_M_BIT 12
|
||||
#define USART_CR1_WAKE_BIT 11
|
||||
#define USART_CR1_PCE_BIT 10
|
||||
#define USART_CR1_PS_BIT 9
|
||||
#define USART_CR1_PEIE_BIT 8
|
||||
#define USART_CR1_TXEIE_BIT 7
|
||||
#define USART_CR1_TCIE_BIT 6
|
||||
#define USART_CR1_RXNEIE_BIT 5
|
||||
#define USART_CR1_IDLEIE_BIT 4
|
||||
#define USART_CR1_TE_BIT 3
|
||||
#define USART_CR1_RE_BIT 2
|
||||
#define USART_CR1_RWU_BIT 1
|
||||
#define USART_CR1_SBK_BIT 0
|
||||
|
||||
#define USART_CR1_UE BIT(USART_CR1_UE_BIT)
|
||||
#define USART_CR1_M BIT(USART_CR1_M_BIT)
|
||||
#define USART_CR1_WAKE BIT(USART_CR1_WAKE_BIT)
|
||||
#define USART_CR1_WAKE_IDLE (0 << USART_CR1_WAKE_BIT)
|
||||
#define USART_CR1_WAKE_ADDR (1 << USART_CR1_WAKE_BIT)
|
||||
#define USART_CR1_PCE BIT(USART_CR1_PCE_BIT)
|
||||
#define USART_CR1_PS BIT(USART_CR1_PS_BIT)
|
||||
#define USART_CR1_PS_EVEN (0 << USART_CR1_PS_BIT)
|
||||
#define USART_CR1_PS_ODD (1 << USART_CR1_PS_BIT)
|
||||
#define USART_CR1_PEIE BIT(USART_CR1_PEIE_BIT)
|
||||
#define USART_CR1_TXEIE BIT(USART_CR1_TXEIE_BIT)
|
||||
#define USART_CR1_TCIE BIT(USART_CR1_TCIE_BIT)
|
||||
#define USART_CR1_RXNEIE BIT(USART_CR1_RXNEIE_BIT)
|
||||
#define USART_CR1_IDLEIE BIT(USART_CR1_IDLEIE_BIT)
|
||||
#define USART_CR1_TE BIT(USART_CR1_TE_BIT)
|
||||
#define USART_CR1_RE BIT(USART_CR1_RE_BIT)
|
||||
#define USART_CR1_RWU BIT(USART_CR1_RWU_BIT)
|
||||
#define USART_CR1_RWU_ACTIVE (0 << USART_CR1_RWU_BIT)
|
||||
#define USART_CR1_RWU_MUTE (1 << USART_CR1_RWU_BIT)
|
||||
#define USART_CR1_SBK BIT(USART_CR1_SBK_BIT)
|
||||
|
||||
/* Control register 2 */
|
||||
|
||||
#define USART_CR2_LINEN_BIT 14
|
||||
#define USART_CR2_CLKEN_BIT 11
|
||||
#define USART_CR2_CPOL_BIT 10
|
||||
#define USART_CR2_CPHA_BIT 9
|
||||
#define USART_CR2_LBCL_BIT 8
|
||||
#define USART_CR2_LBDIE_BIT 6
|
||||
#define USART_CR2_LBDL_BIT 5
|
||||
|
||||
#define USART_CR2_LINEN BIT(USART_CR2_LINEN_BIT)
|
||||
#define USART_CR2_STOP (0x3 << 12)
|
||||
#define USART_CR2_STOP_BITS_1 (0x0 << 12)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR2_STOP_BITS_POINT_5 (0x1 << 12)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12)
|
||||
#define USART_CR2_STOP_BITS_2 (0x2 << 12)
|
||||
#define USART_CR2_CLKEN BIT(USART_CR2_CLKEN_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR2_CPOL BIT(USART_CR2_CPOL_BIT)
|
||||
#define USART_CR2_CPOL_LOW (0x0 << USART_CR2_CLKEN_BIT)
|
||||
#define USART_CR2_CPOL_HIGH (0x1 << USART_CR2_CLKEN_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR2_CPHA BIT(USART_CR2_CPHA_BIT)
|
||||
#define USART_CR2_CPHA_FIRST (0x0 << USART_CR2_CPHA_BIT)
|
||||
#define USART_CR2_CPHA_SECOND (0x1 << USART_CR2_CPHA_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR2_LBCL BIT(USART_CR2_LBCL_BIT)
|
||||
#define USART_CR2_LBDIE BIT(USART_CR2_LBDIE_BIT)
|
||||
#define USART_CR2_LBDL BIT(USART_CR2_LBDL_BIT)
|
||||
#define USART_CR2_LBDL_10_BIT (0 << USART_CR2_LBDL_BIT)
|
||||
#define USART_CR2_LBDL_11_BIT (1 << USART_CR2_LBDL_BIT)
|
||||
#define USART_CR2_ADD 0xF
|
||||
|
||||
/* Control register 3 */
|
||||
|
||||
#define USART_CR3_CTSIE_BIT 10
|
||||
#define USART_CR3_CTSE_BIT 9
|
||||
#define USART_CR3_RTSE_BIT 8
|
||||
#define USART_CR3_DMAT_BIT 7
|
||||
#define USART_CR3_DMAR_BIT 6
|
||||
#define USART_CR3_SCEN_BIT 5
|
||||
#define USART_CR3_NACK_BIT 4
|
||||
#define USART_CR3_HDSEL_BIT 3
|
||||
#define USART_CR3_IRLP_BIT 2
|
||||
#define USART_CR3_IREN_BIT 1
|
||||
#define USART_CR3_EIE_BIT 0
|
||||
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR3_CTSIE BIT(USART_CR3_CTSIE_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR3_CTSE BIT(USART_CR3_CTSE_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR3_RTSE BIT(USART_CR3_RTSE_BIT)
|
||||
/* Not on UART5 */
|
||||
#define USART_CR3_DMAT BIT(USART_CR3_DMAT_BIT)
|
||||
/* Not on UART5 */
|
||||
#define USART_CR3_DMAR BIT(USART_CR3_DMAR_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR3_SCEN BIT(USART_CR3_SCEN_BIT)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_CR3_NACK BIT(USART_CR3_NACK_BIT)
|
||||
#define USART_CR3_HDSEL BIT(USART_CR3_HDSEL_BIT)
|
||||
#define USART_CR3_IRLP BIT(USART_CR3_IRLP_BIT)
|
||||
#define USART_CR3_IRLP_NORMAL (0 << USART_CR3_IRLP_BIT)
|
||||
#define USART_CR3_IRLP_LOW_POWER (1 << USART_CR3_IRLP_BIT)
|
||||
#define USART_CR3_IREN BIT(USART_CR3_IREN_BIT)
|
||||
#define USART_CR3_EIE BIT(USART_CR3_EIE_BIT)
|
||||
|
||||
/* Guard time and prescaler register */
|
||||
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_GTPR_GT (0xFF << 8)
|
||||
/* Not on UART4, UART5 */
|
||||
#define USART_GTPR_PSC 0xFF
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
#ifndef USART_RX_BUF_SIZE
|
||||
#define USART_RX_BUF_SIZE 256
|
||||
#endif
|
||||
|
||||
#ifndef USART_TX_BUF_SIZE
|
||||
#define USART_TX_BUF_SIZE 256
|
||||
#endif
|
||||
|
||||
/** USART device type */
|
||||
typedef struct usart_dev {
|
||||
usart_reg_map *regs; /**< Register map */
|
||||
ring_buffer rbRX; /**< RX ring buffer */
|
||||
ring_buffer rbTX; /**< RX ring buffer */
|
||||
uint32 max_baud; /**< Maximum baud */
|
||||
uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated.
|
||||
* Actual RX buffer used by rb.
|
||||
* This field will be removed in
|
||||
* a future release. */
|
||||
uint8 tx_buf[USART_TX_BUF_SIZE];
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
nvic_irq_num irq_num; /**< USART NVIC interrupt */
|
||||
} usart_dev;
|
||||
|
||||
extern usart_dev *USART1;
|
||||
extern usart_dev *USART2;
|
||||
extern usart_dev *USART3;
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
extern usart_dev *UART4;
|
||||
extern usart_dev *UART5;
|
||||
#endif
|
||||
|
||||
void usart_init(usart_dev *dev);
|
||||
void usart_set_baud_rate(usart_dev *dev, uint32 baud);
|
||||
void usart_enable(usart_dev *dev);
|
||||
void usart_disable(usart_dev *dev);
|
||||
void usart_foreach(void (*fn)(usart_dev *dev));
|
||||
uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len);
|
||||
void usart_putudec(usart_dev *dev, uint32 val);
|
||||
|
||||
/**
|
||||
* @brief Disable all serial ports.
|
||||
*/
|
||||
static inline void usart_disable_all(void) {
|
||||
usart_foreach(usart_disable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit one character on a serial port.
|
||||
*
|
||||
* This function blocks until the character has been successfully
|
||||
* transmitted.
|
||||
*
|
||||
* @param dev Serial port to send on.
|
||||
* @param byte Byte to transmit.
|
||||
*/
|
||||
static inline void usart_putc(usart_dev* dev, uint8 byte) {
|
||||
while (!usart_tx(dev, &byte, 1))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit a character string on a serial port.
|
||||
*
|
||||
* This function blocks until str is completely transmitted.
|
||||
*
|
||||
* @param dev Serial port to send on
|
||||
* @param str String to send
|
||||
*/
|
||||
static inline void usart_putstr(usart_dev *dev, const char* str) {
|
||||
uint32 i = 0;
|
||||
while (str[i] != '\0') {
|
||||
usart_putc(dev, str[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one character from a serial port.
|
||||
*
|
||||
* It's not safe to call this function if the serial port has no data
|
||||
* available.
|
||||
*
|
||||
* @param dev Serial port to read from
|
||||
* @return byte read
|
||||
* @see usart_data_available()
|
||||
*/
|
||||
static inline uint8 usart_getc(usart_dev *dev) {
|
||||
return rb_remove(&dev->rbRX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the amount of data available in a serial port's RX buffer.
|
||||
* @param dev Serial port to check
|
||||
* @return Number of bytes in dev's RX buffer.
|
||||
*/
|
||||
static inline uint32 usart_data_available(usart_dev *dev) {
|
||||
return rb_full_count(&dev->rbRX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the amount of data available in a serial port's TX buffer.
|
||||
* @param dev Serial port to check
|
||||
* @return Number of bytes in dev's TX buffer.
|
||||
*/
|
||||
static inline uint32 usart_data_pending(usart_dev *dev) {
|
||||
return rb_full_count(&dev->rbTX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discard the contents of a serial port's RX buffer.
|
||||
* @param dev Serial port whose buffer to empty.
|
||||
*/
|
||||
static inline void usart_reset_rx(usart_dev *dev) {
|
||||
rb_reset(&dev->rbRX);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // _USART_H_
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_audio_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_audio_core.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __USB_AUDIO_CORE_H_
|
||||
#define __USB_AUDIO_CORE_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
#include "usbd_req.h"
|
||||
#include "usbd_desc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_audio
|
||||
* @brief This file is the Header file for USBD_audio.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_audio_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* AudioFreq * DataSize (2 bytes) * NumChannels (Stereo: 2) */
|
||||
#define AUDIO_OUT_PACKET (uint32_t)(((USBD_AUDIO_FREQ * 2 * 2) /1000))
|
||||
|
||||
/* Number of sub-packets in the audio transfer buffer. You can modify this value but always make sure
|
||||
that it is an even number and higher than 3 */
|
||||
#define OUT_PACKET_NUM 4
|
||||
/* Total size of the audio transfer buffer */
|
||||
#define TOTAL_OUT_BUF_SIZE ((uint32_t)(AUDIO_OUT_PACKET * OUT_PACKET_NUM))
|
||||
|
||||
#define AUDIO_CONFIG_DESC_SIZE 109
|
||||
#define AUDIO_INTERFACE_DESC_SIZE 9
|
||||
#define USB_AUDIO_DESC_SIZ 0x09
|
||||
#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09
|
||||
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07
|
||||
|
||||
#define AUDIO_DESCRIPTOR_TYPE 0x21
|
||||
#define USB_DEVICE_CLASS_AUDIO 0x01
|
||||
#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
|
||||
#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
|
||||
#define AUDIO_PROTOCOL_UNDEFINED 0x00
|
||||
#define AUDIO_STREAMING_GENERAL 0x01
|
||||
#define AUDIO_STREAMING_FORMAT_TYPE 0x02
|
||||
|
||||
/* Audio Descriptor Types */
|
||||
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
|
||||
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
|
||||
|
||||
/* Audio Control Interface Descriptor Subtypes */
|
||||
#define AUDIO_CONTROL_HEADER 0x01
|
||||
#define AUDIO_CONTROL_INPUT_TERMINAL 0x02
|
||||
#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03
|
||||
#define AUDIO_CONTROL_FEATURE_UNIT 0x06
|
||||
|
||||
#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C
|
||||
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09
|
||||
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07
|
||||
|
||||
#define AUDIO_CONTROL_MUTE 0x0001
|
||||
|
||||
#define AUDIO_FORMAT_TYPE_I 0x01
|
||||
#define AUDIO_FORMAT_TYPE_III 0x03
|
||||
|
||||
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
|
||||
#define AUDIO_ENDPOINT_GENERAL 0x01
|
||||
|
||||
#define AUDIO_REQ_GET_CUR 0x81
|
||||
#define AUDIO_REQ_SET_CUR 0x01
|
||||
|
||||
#define AUDIO_OUT_STREAMING_CTRL 0x02
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
typedef struct _Audio_Fops
|
||||
{
|
||||
uint8_t (*Init) (uint32_t AudioFreq, uint32_t Volume, uint32_t options);
|
||||
uint8_t (*DeInit) (uint32_t options);
|
||||
uint8_t (*AudioCmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd);
|
||||
uint8_t (*VolumeCtl) (uint8_t vol);
|
||||
uint8_t (*MuteCtl) (uint8_t cmd);
|
||||
uint8_t (*PeriodicTC) (uint8_t cmd);
|
||||
uint8_t (*GetState) (void);
|
||||
}AUDIO_FOPS_TypeDef;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
#define AUDIO_PACKET_SZE(frq) (uint8_t)(((frq * 2 * 2)/1000) & 0xFF), \
|
||||
(uint8_t)((((frq * 2 * 2)/1000) >> 8) & 0xFF)
|
||||
#define SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern USBD_Class_cb_TypeDef AUDIO_cb;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __USB_AUDIO_CORE_H_
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_audio_out_if.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_audio_out_if.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __USB_AUDIO_OUT_IF_H_
|
||||
#define __USB_AUDIO_OUT_IF_H_
|
||||
|
||||
#ifdef STM32F2XX
|
||||
#include "stm322xg_usb_audio_codec.h"
|
||||
#elif defined(STM32F10X_CL)
|
||||
#include "stm3210c_usb_audio_codec.h"
|
||||
#endif /* STM32F2XX */
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_audio
|
||||
* @brief This file is the Header file for USBD_audio.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_audio_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
/* Audio Commands enmueration */
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CMD_PLAY = 1,
|
||||
AUDIO_CMD_PAUSE,
|
||||
AUDIO_CMD_STOP,
|
||||
}AUDIO_CMD_TypeDef;
|
||||
|
||||
/* Mute commands */
|
||||
#define AUDIO_MUTE 0x01
|
||||
#define AUDIO_UNMUTE 0x00
|
||||
|
||||
/* Functions return value */
|
||||
#define AUDIO_OK 0x00
|
||||
#define AUDIO_FAIL 0xFF
|
||||
|
||||
/* Audio Machine States */
|
||||
#define AUDIO_STATE_INACTIVE 0x00
|
||||
#define AUDIO_STATE_ACTIVE 0x01
|
||||
#define AUDIO_STATE_PLAYING 0x02
|
||||
#define AUDIO_STATE_PAUSED 0x03
|
||||
#define AUDIO_STATE_STOPPED 0x04
|
||||
#define AUDIO_STATE_ERROR 0x05
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern AUDIO_FOPS_TypeDef AUDIO_OUT_fops;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USB_AUDIO_OUT_IF_H_ */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_cdc_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_cdc_core.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __USB_CDC_CORE_H_
|
||||
#define __USB_CDC_CORE_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_cdc
|
||||
* @brief This file is the Header file for USBD_cdc.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_cdc_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USB_CDC_CONFIG_DESC_SIZ (67)
|
||||
#define USB_CDC_DESC_SIZ (67-9)
|
||||
|
||||
#define CDC_DESCRIPTOR_TYPE 0x21
|
||||
|
||||
#define DEVICE_CLASS_CDC 0x02
|
||||
#define DEVICE_SUBCLASS_CDC 0x00
|
||||
|
||||
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 0x03
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
|
||||
|
||||
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
|
||||
|
||||
#define CDC_DATA_IN_PACKET_SIZE *(uint16_t *)(((USB_OTG_CORE_HANDLE *)pdev)->dev.pConfig_descriptor + 57)
|
||||
|
||||
#define CDC_DATA_OUT_PACKET_SIZE *(uint16_t *)(((USB_OTG_CORE_HANDLE *)pdev)->dev.pConfig_descriptor + 64)
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* CDC definitions */
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
/**************************************************/
|
||||
/* CDC Requests */
|
||||
/**************************************************/
|
||||
#define SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define SET_COMM_FEATURE 0x02
|
||||
#define GET_COMM_FEATURE 0x03
|
||||
#define CLEAR_COMM_FEATURE 0x04
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
#define SEND_BREAK 0x23
|
||||
#define NO_CMD 0xFF
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
typedef struct _CDC_IF_PROP
|
||||
{
|
||||
uint16_t (*pIf_Init) (void);
|
||||
uint16_t (*pIf_DeInit) (void);
|
||||
uint16_t (*pIf_Ctrl) (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
|
||||
uint16_t (*pIf_DataTx) (uint8_t* Buf, uint32_t Len);
|
||||
uint16_t (*pIf_DataRx) (uint8_t* Buf, uint32_t Len);
|
||||
}
|
||||
CDC_IF_Prop_TypeDef;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern USBD_Class_cb_TypeDef USBD_CDC_cb;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __USB_CDC_CORE_H_
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_cdc_if_template.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief Header for dfu_mal.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_CDC_IF_TEMPLATE_H
|
||||
#define __USBD_CDC_IF_TEMPLATE_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#ifdef STM32F2XX
|
||||
#include "stm32f2xx.h"
|
||||
#elif defined(STM32F10X_CL)
|
||||
#include "stm32f10x.h"
|
||||
#endif /* STM32F2XX */
|
||||
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_cdc_core.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
extern CDC_IF_Prop_TypeDef TEMPLATE_fops;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
#endif /* __USBD_CDC_IF_TEMPLATE_H */
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,869 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_cdc_core.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief This file provides the high layer firmware functions to manage the
|
||||
* following functionalities of the USB CDC Class:
|
||||
* - Initialization and Configuration of high and low layer
|
||||
* - Enumeration as CDC Device (and enumeration for each implemented memory interface)
|
||||
* - OUT/IN data transfer
|
||||
* - Command IN transfer (class requests management)
|
||||
* - Error management
|
||||
*
|
||||
* @verbatim
|
||||
*
|
||||
* ===================================================================
|
||||
* CDC Class Driver Description
|
||||
* ===================================================================
|
||||
* This driver manages the "Universal Serial Bus Class Definitions for Communications Devices
|
||||
* Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus
|
||||
* Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007"
|
||||
* This driver implements the following aspects of the specification:
|
||||
* - Device descriptor management
|
||||
* - Configuration descriptor management
|
||||
* - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
|
||||
* - Requests management (as described in section 6.2 in specification)
|
||||
* - Abstract Control Model compliant
|
||||
* - Union Functional collection (using 1 IN endpoint for control)
|
||||
* - Data interface class
|
||||
|
||||
* @note
|
||||
* For the Abstract Control Model, this core allows only transmitting the requests to
|
||||
* lower layer dispatcher (ie. usbd_cdc_vcp.c/.h) which should manage each request and
|
||||
* perform relative actions.
|
||||
*
|
||||
* These aspects may be enriched or modified for a specific user application.
|
||||
*
|
||||
* This driver doesn't implement the following aspects of the specification
|
||||
* (but it is possible to manage these features with some modifications on this driver):
|
||||
* - Any class-specific aspect relative to communication classes should be managed by user application.
|
||||
* - All communication classes other than PSTN are not managed
|
||||
*
|
||||
* @endverbatim
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_cdc_core.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_req.h"
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_cdc
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_cdc_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_cdc_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_cdc_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_cdc_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*********************************************
|
||||
CDC Device library callbacks
|
||||
*********************************************/
|
||||
static uint8_t usbd_cdc_Init (void *pdev, uint8_t cfgidx);
|
||||
static uint8_t usbd_cdc_DeInit (void *pdev, uint8_t cfgidx);
|
||||
static uint8_t usbd_cdc_Setup (void *pdev, USB_SETUP_REQ *req);
|
||||
static uint8_t usbd_cdc_EP0_RxReady (void *pdev);
|
||||
static uint8_t usbd_cdc_DataIn (void *pdev, uint8_t epnum);
|
||||
static uint8_t usbd_cdc_DataOut (void *pdev, uint8_t epnum);
|
||||
static uint8_t usbd_cdc_SOF (void *pdev);
|
||||
|
||||
/*********************************************
|
||||
CDC specific management functions
|
||||
*********************************************/
|
||||
static void Handle_USBAsynchXfer (void *pdev);
|
||||
static uint8_t *USBD_cdc_GetCfgDesc (uint8_t speed, uint16_t *length);
|
||||
#ifdef USE_USB_OTG_HS
|
||||
static uint8_t *USBD_cdc_GetOtherCfgDesc (uint8_t speed, uint16_t *length);
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_cdc_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
extern CDC_IF_Prop_TypeDef APP_FOPS;
|
||||
extern uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC];
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN uint8_t usbd_cdc_CfgDesc [USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END ;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN uint8_t usbd_cdc_OtherCfgDesc [USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END ;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static __IO uint32_t usbd_cdc_AltSet __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN uint8_t USB_Rx_Buffer [CDC_DATA_MAX_PACKET_SIZE] __ALIGN_END ;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN uint8_t APP_Rx_Buffer [APP_RX_DATA_SIZE] __ALIGN_END ;
|
||||
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN uint8_t CmdBuff[CDC_CMD_PACKET_SZE] __ALIGN_END ;
|
||||
|
||||
volatile int APP_Rx_ptr_in = 0;
|
||||
volatile int APP_Rx_ptr_out = 0;
|
||||
uint32_t APP_Rx_length = 0;
|
||||
|
||||
uint8_t USB_Tx_State = 0;
|
||||
|
||||
static uint32_t cdcCmd = 0xFF;
|
||||
static uint32_t cdcLen = 0;
|
||||
|
||||
/* CDC interface class callbacks structure */
|
||||
USBD_Class_cb_TypeDef USBD_CDC_cb =
|
||||
{
|
||||
usbd_cdc_Init,
|
||||
usbd_cdc_DeInit,
|
||||
usbd_cdc_Setup,
|
||||
NULL, /* EP0_TxSent, */
|
||||
usbd_cdc_EP0_RxReady,
|
||||
usbd_cdc_DataIn,
|
||||
usbd_cdc_DataOut,
|
||||
usbd_cdc_SOF,
|
||||
NULL,
|
||||
NULL,
|
||||
USBD_cdc_GetCfgDesc,
|
||||
#ifdef USE_USB_OTG_HS
|
||||
USBD_cdc_GetOtherCfgDesc, /* use same cobfig as per FS */
|
||||
#endif /* USE_USB_OTG_HS */
|
||||
};
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
/* USB CDC device Configuration Descriptor */
|
||||
__ALIGN_BEGIN uint8_t usbd_cdc_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
/*Configuration Descriptor*/
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
|
||||
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
|
||||
0x00,
|
||||
0x02, /* bNumInterfaces: 2 interface */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
0xC0, /* bmAttributes: self powered */
|
||||
0x32, /* MaxPower 0 mA */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
0x01, /* bDataInterface: 1 */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x00, /* bMasterInterface: Communication class interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SZE),
|
||||
#ifdef USE_USB_OTG_HS
|
||||
0x10, /* bInterval: */
|
||||
#else
|
||||
0xFF, /* bInterval: */
|
||||
#endif /* USE_USB_OTG_HS */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00 /* bInterval: ignore for Bulk transfer */
|
||||
} ;
|
||||
|
||||
#ifdef USE_USB_OTG_HS
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN uint8_t usbd_cdc_OtherCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
0x09, /* bLength: Configuation Descriptor size */
|
||||
USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION,
|
||||
USB_CDC_CONFIG_DESC_SIZ,
|
||||
0x00,
|
||||
0x02, /* bNumInterfaces: 2 interfaces */
|
||||
0x01, /* bConfigurationValue: */
|
||||
0x04, /* iConfiguration: */
|
||||
0xC0, /* bmAttributes: */
|
||||
0x32, /* MaxPower 100 mA */
|
||||
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
0x01, /* bDataInterface: 1 */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x00, /* bMasterInterface: Communication class interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SZE),
|
||||
0xFF, /* bInterval: */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
0x40, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
0x40, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0x00 /* bInterval */
|
||||
};
|
||||
#endif /* USE_USB_OTG_HS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_cdc_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief usbd_cdc_Init
|
||||
* Initilaize the CDC interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t usbd_cdc_Init (void *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
uint8_t *pbuf;
|
||||
|
||||
/* Open EP IN */
|
||||
DCD_EP_Open(pdev,
|
||||
CDC_IN_EP,
|
||||
CDC_DATA_IN_PACKET_SIZE,
|
||||
USB_OTG_EP_BULK);
|
||||
|
||||
/* Open EP OUT */
|
||||
DCD_EP_Open(pdev,
|
||||
CDC_OUT_EP,
|
||||
CDC_DATA_OUT_PACKET_SIZE,
|
||||
USB_OTG_EP_BULK);
|
||||
|
||||
/* Open Command IN EP */
|
||||
DCD_EP_Open(pdev,
|
||||
CDC_CMD_EP,
|
||||
CDC_CMD_PACKET_SZE,
|
||||
USB_OTG_EP_INT);
|
||||
|
||||
pbuf = (uint8_t *)USBD_DeviceDesc;
|
||||
pbuf[4] = DEVICE_CLASS_CDC;
|
||||
pbuf[5] = DEVICE_SUBCLASS_CDC;
|
||||
|
||||
/* Initialize the Interface physical components */
|
||||
APP_FOPS.pIf_Init();
|
||||
|
||||
/* Prepare Out endpoint to receive next packet */
|
||||
DCD_EP_PrepareRx(pdev,
|
||||
CDC_OUT_EP,
|
||||
(uint8_t*)(USB_Rx_Buffer),
|
||||
CDC_DATA_OUT_PACKET_SIZE);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usbd_cdc_Init
|
||||
* DeInitialize the CDC layer
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t usbd_cdc_DeInit (void *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
/* Open EP IN */
|
||||
DCD_EP_Close(pdev,
|
||||
CDC_IN_EP);
|
||||
|
||||
/* Open EP OUT */
|
||||
DCD_EP_Close(pdev,
|
||||
CDC_OUT_EP);
|
||||
|
||||
/* Open Command IN EP */
|
||||
DCD_EP_Close(pdev,
|
||||
CDC_CMD_EP);
|
||||
|
||||
/* Restore default state of the Interface physical components */
|
||||
APP_FOPS.pIf_DeInit();
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usbd_cdc_Setup
|
||||
* Handle the CDC specific requests
|
||||
* @param pdev: instance
|
||||
* @param req: usb requests
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t usbd_cdc_Setup (void *pdev,
|
||||
USB_SETUP_REQ *req)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t *pbuf;
|
||||
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
/* CDC Class Requests -------------------------------*/
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
/* Check if the request is a data setup packet */
|
||||
if (req->wLength)
|
||||
{
|
||||
/* Check if the request is Device-to-Host */
|
||||
if (req->bmRequest & 0x80)
|
||||
{
|
||||
/* Get the data to be sent to Host from interface layer */
|
||||
APP_FOPS.pIf_Ctrl(req->bRequest, CmdBuff, req->wLength);
|
||||
|
||||
/* Send the data to the host */
|
||||
USBD_CtlSendData (pdev,
|
||||
CmdBuff,
|
||||
req->wLength);
|
||||
}
|
||||
else /* Host-to-Device requeset */
|
||||
{
|
||||
/* Set the value of the current command to be processed */
|
||||
cdcCmd = req->bRequest;
|
||||
cdcLen = req->wLength;
|
||||
|
||||
/* Prepare the reception of the buffer over EP0
|
||||
Next step: the received data will be managed in usbd_cdc_EP0_TxSent()
|
||||
function. */
|
||||
USBD_CtlPrepareRx (pdev,
|
||||
CmdBuff,
|
||||
req->wLength);
|
||||
}
|
||||
}
|
||||
else /* No Data request */
|
||||
{
|
||||
/* Transfer the command to the interface layer */
|
||||
APP_FOPS.pIf_Ctrl(req->bRequest, (uint8_t*)&req->wValue, sizeof(req->wValue));
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
return USBD_FAIL;
|
||||
|
||||
|
||||
|
||||
/* Standard Requests -------------------------------*/
|
||||
case USB_REQ_TYPE_STANDARD:
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
if( (req->wValue >> 8) == CDC_DESCRIPTOR_TYPE)
|
||||
{
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
pbuf = usbd_cdc_Desc;
|
||||
#else
|
||||
pbuf = usbd_cdc_CfgDesc + 9 + (9 * USBD_ITF_MAX_NUM);
|
||||
#endif
|
||||
len = MIN(USB_CDC_DESC_SIZ , req->wLength);
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
pbuf,
|
||||
len);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_INTERFACE :
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&usbd_cdc_AltSet,
|
||||
1);
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE :
|
||||
if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM)
|
||||
{
|
||||
usbd_cdc_AltSet = (uint8_t)(req->wValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call the error management function (command will be nacked */
|
||||
USBD_CtlError (pdev, req);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usbd_cdc_EP0_RxReady
|
||||
* Data received on control endpoint
|
||||
* @param pdev: device device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t usbd_cdc_EP0_RxReady (void *pdev)
|
||||
{
|
||||
if (cdcCmd != NO_CMD)
|
||||
{
|
||||
/* Process the data */
|
||||
APP_FOPS.pIf_Ctrl(cdcCmd, CmdBuff, cdcLen);
|
||||
|
||||
/* Reset the command variable to default value */
|
||||
cdcCmd = NO_CMD;
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usbd_audio_DataIn
|
||||
* Data sent on non-control IN endpoint
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
#if 0
|
||||
static uint8_t usbd_cdc_DataIn (void *pdev, uint8_t epnum)
|
||||
{
|
||||
uint16_t USB_Tx_ptr;
|
||||
uint16_t USB_Tx_length;
|
||||
|
||||
if (USB_Tx_State == 1)
|
||||
{
|
||||
if (APP_Rx_length == 0)
|
||||
{
|
||||
USB_Tx_State = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (APP_Rx_length > CDC_DATA_IN_PACKET_SIZE){
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = CDC_DATA_IN_PACKET_SIZE;
|
||||
|
||||
APP_Rx_ptr_out += CDC_DATA_IN_PACKET_SIZE;
|
||||
APP_Rx_length -= CDC_DATA_IN_PACKET_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = APP_Rx_length;
|
||||
|
||||
APP_Rx_ptr_out += APP_Rx_length;
|
||||
APP_Rx_length = 0;
|
||||
}
|
||||
|
||||
/* Prepare the available data buffer to be sent on IN endpoint */
|
||||
DCD_EP_Tx (pdev,
|
||||
CDC_IN_EP,
|
||||
(uint8_t*)&APP_Rx_Buffer[USB_Tx_ptr],
|
||||
USB_Tx_length);
|
||||
}
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ala42: applied fix from
|
||||
//https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2fpublic%2f
|
||||
//STe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fUSB%20CDC%20Device%20hung%20fix&
|
||||
//FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=75
|
||||
static uint8_t usbd_cdc_DataIn (void *pdev, uint8_t epnum)
|
||||
{
|
||||
uint16_t USB_Tx_ptr;
|
||||
uint16_t USB_Tx_length;
|
||||
|
||||
if (USB_Tx_State == 1)
|
||||
{
|
||||
if (APP_Rx_length == 0)
|
||||
{
|
||||
if (((USB_OTG_CORE_HANDLE*)pdev)->dev.in_ep[epnum].xfer_len != CDC_DATA_IN_PACKET_SIZE)
|
||||
{
|
||||
USB_Tx_State = 0;
|
||||
return USBD_OK;
|
||||
}
|
||||
/* Transmit zero sized packet in case the last one has maximum allowed size. Otherwise
|
||||
* the recipient may expect more data coming soon and not return buffered data to app.
|
||||
* See section 5.8.3 Bulk Transfer Packet Size Constraints
|
||||
* of the USB Specification document.
|
||||
*/
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (APP_Rx_length > CDC_DATA_IN_PACKET_SIZE){
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = CDC_DATA_IN_PACKET_SIZE;
|
||||
|
||||
APP_Rx_ptr_out += CDC_DATA_IN_PACKET_SIZE;
|
||||
APP_Rx_length -= CDC_DATA_IN_PACKET_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = APP_Rx_length;
|
||||
|
||||
APP_Rx_ptr_out += APP_Rx_length;
|
||||
APP_Rx_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare the available data buffer to be sent on IN endpoint */
|
||||
DCD_EP_Tx (pdev,
|
||||
CDC_IN_EP,
|
||||
(uint8_t*)&APP_Rx_Buffer[USB_Tx_ptr],
|
||||
USB_Tx_length);
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief usbd_audio_DataOut
|
||||
* Data received on non-control Out endpoint
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t usbd_cdc_DataOut (void *pdev, uint8_t epnum)
|
||||
{
|
||||
uint16_t USB_Rx_Cnt;
|
||||
|
||||
/* Get the received data buffer and update the counter */
|
||||
USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count;
|
||||
|
||||
/* USB data will be immediately processed, this allow next USB traffic being
|
||||
NAKed till the end of the application Xfer */
|
||||
APP_FOPS.pIf_DataRx(USB_Rx_Buffer, USB_Rx_Cnt);
|
||||
|
||||
/* Prepare Out endpoint to receive next packet */
|
||||
DCD_EP_PrepareRx(pdev,
|
||||
CDC_OUT_EP,
|
||||
(uint8_t*)(USB_Rx_Buffer),
|
||||
CDC_DATA_OUT_PACKET_SIZE);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usbd_audio_SOF
|
||||
* Start Of Frame event management
|
||||
* @param pdev: instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t usbd_cdc_SOF (void *pdev)
|
||||
{
|
||||
static uint32_t FrameCount = 0;
|
||||
|
||||
if (FrameCount++ == CDC_IN_FRAME_INTERVAL)
|
||||
{
|
||||
/* Reset the frame counter */
|
||||
FrameCount = 0;
|
||||
|
||||
/* Check the data to be sent through IN pipe */
|
||||
Handle_USBAsynchXfer(pdev);
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle_USBAsynchXfer
|
||||
* Send data to USB
|
||||
* @param pdev: instance
|
||||
* @retval None
|
||||
*/
|
||||
static void Handle_USBAsynchXfer (void *pdev)
|
||||
{
|
||||
uint16_t USB_Tx_ptr;
|
||||
uint16_t USB_Tx_length;
|
||||
|
||||
if(USB_Tx_State != 1)
|
||||
{
|
||||
if (APP_Rx_ptr_out == APP_RX_DATA_SIZE)
|
||||
{
|
||||
APP_Rx_ptr_out = 0;
|
||||
}
|
||||
|
||||
if(APP_Rx_ptr_out == APP_Rx_ptr_in)
|
||||
{
|
||||
USB_Tx_State = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(APP_Rx_ptr_out > APP_Rx_ptr_in) /* rollback */
|
||||
{
|
||||
APP_Rx_length = APP_RX_DATA_SIZE - APP_Rx_ptr_out;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_Rx_length = APP_Rx_ptr_in - APP_Rx_ptr_out;
|
||||
|
||||
}
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
APP_Rx_length &= ~0x03;
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
if (APP_Rx_length > CDC_DATA_IN_PACKET_SIZE)
|
||||
{
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = CDC_DATA_IN_PACKET_SIZE;
|
||||
|
||||
APP_Rx_ptr_out += CDC_DATA_IN_PACKET_SIZE;
|
||||
APP_Rx_length -= CDC_DATA_IN_PACKET_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_Tx_ptr = APP_Rx_ptr_out;
|
||||
USB_Tx_length = APP_Rx_length;
|
||||
|
||||
APP_Rx_ptr_out += APP_Rx_length;
|
||||
APP_Rx_length = 0;
|
||||
}
|
||||
USB_Tx_State = 1;
|
||||
|
||||
DCD_EP_Tx (pdev,
|
||||
CDC_IN_EP,
|
||||
(uint8_t*)&APP_Rx_Buffer[USB_Tx_ptr],
|
||||
USB_Tx_length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_cdc_GetCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static uint8_t *USBD_cdc_GetCfgDesc (uint8_t speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof (usbd_cdc_CfgDesc);
|
||||
return usbd_cdc_CfgDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_cdc_GetCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
#ifdef USE_USB_OTG_HS
|
||||
static uint8_t *USBD_cdc_GetOtherCfgDesc (uint8_t speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof (usbd_cdc_OtherCfgDesc);
|
||||
return usbd_cdc_OtherCfgDesc;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_dfu_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_dfu_core.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __USB_DFU_CORE_H_
|
||||
#define __USB_DFU_CORE_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
#include "usbd_dfu_mal.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup usbd_dfu
|
||||
* @brief This file is the Header file for USBD_dfu.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup usbd_dfu_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USB_DFU_CONFIG_DESC_SIZ (18 + (9 * USBD_ITF_MAX_NUM))
|
||||
#define USB_DFU_DESC_SIZ 9
|
||||
|
||||
#define DFU_DESCRIPTOR_TYPE 0x21
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* DFU definitions */
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/* DFU Requests DFU states */
|
||||
/**************************************************/
|
||||
|
||||
|
||||
#define STATE_appIDLE 0
|
||||
#define STATE_appDETACH 1
|
||||
#define STATE_dfuIDLE 2
|
||||
#define STATE_dfuDNLOAD_SYNC 3
|
||||
#define STATE_dfuDNBUSY 4
|
||||
#define STATE_dfuDNLOAD_IDLE 5
|
||||
#define STATE_dfuMANIFEST_SYNC 6
|
||||
#define STATE_dfuMANIFEST 7
|
||||
#define STATE_dfuMANIFEST_WAIT_RESET 8
|
||||
#define STATE_dfuUPLOAD_IDLE 9
|
||||
#define STATE_dfuERROR 10
|
||||
|
||||
/**************************************************/
|
||||
/* DFU Requests DFU status */
|
||||
/**************************************************/
|
||||
|
||||
#define STATUS_OK 0x00
|
||||
#define STATUS_ERRTARGET 0x01
|
||||
#define STATUS_ERRFILE 0x02
|
||||
#define STATUS_ERRWRITE 0x03
|
||||
#define STATUS_ERRERASE 0x04
|
||||
#define STATUS_ERRCHECK_ERASED 0x05
|
||||
#define STATUS_ERRPROG 0x06
|
||||
#define STATUS_ERRVERIFY 0x07
|
||||
#define STATUS_ERRADDRESS 0x08
|
||||
#define STATUS_ERRNOTDONE 0x09
|
||||
#define STATUS_ERRFIRMWARE 0x0A
|
||||
#define STATUS_ERRVENDOR 0x0B
|
||||
#define STATUS_ERRUSBR 0x0C
|
||||
#define STATUS_ERRPOR 0x0D
|
||||
#define STATUS_ERRUNKNOWN 0x0E
|
||||
#define STATUS_ERRSTALLEDPKT 0x0F
|
||||
|
||||
/**************************************************/
|
||||
/* DFU Requests DFU states Manifestation State */
|
||||
/**************************************************/
|
||||
|
||||
#define Manifest_complete 0x00
|
||||
#define Manifest_In_Progress 0x01
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/* Special Commands with Download Request */
|
||||
/**************************************************/
|
||||
|
||||
#define CMD_GETCOMMANDS 0x00
|
||||
#define CMD_SETADDRESSPOINTER 0x21
|
||||
#define CMD_ERASE 0x41
|
||||
|
||||
/**************************************************/
|
||||
/* Other defines */
|
||||
/**************************************************/
|
||||
/* Bit Detach capable = bit 3 in bmAttributes field */
|
||||
#define DFU_DETACH_MASK (uint8_t)(1 << 4)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**************************************************/
|
||||
/* DFU Requests */
|
||||
/**************************************************/
|
||||
|
||||
typedef enum _DFU_REQUESTS {
|
||||
DFU_DETACH = 0,
|
||||
DFU_DNLOAD = 1,
|
||||
DFU_UPLOAD,
|
||||
DFU_GETSTATUS,
|
||||
DFU_CLRSTATUS,
|
||||
DFU_GETSTATE,
|
||||
DFU_ABORT
|
||||
} DFU_REQUESTS;
|
||||
|
||||
typedef void (*pFunction)(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/********** Descriptor of DFU interface 0 Alternate setting n ****************/
|
||||
#define USBD_DFU_IF_DESC(n) 0x09, /* bLength: Interface Descriptor size */ \
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
0x00, /* bInterfaceNumber: Number of Interface */ \
|
||||
(n), /* bAlternateSetting: Alternate setting */ \
|
||||
0x00, /* bNumEndpoints*/ \
|
||||
0xFE, /* bInterfaceClass: Application Specific Class Code */ \
|
||||
0x01, /* bInterfaceSubClass : Device Firmware Upgrade Code */ \
|
||||
0x02, /* nInterfaceProtocol: DFU mode protocol */ \
|
||||
USBD_IDX_INTERFACE_STR + (n) + 1 /* iInterface: Index of string descriptor */ \
|
||||
/* 18 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern USBD_Class_cb_TypeDef DFU_cb;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __USB_DFU_CORE_H_
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_dfu_mal.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief Header for usbd_dfu_mal.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __DFU_MAL_H
|
||||
#define __DFU_MAL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#ifdef STM32F2XX
|
||||
#include "stm32f2xx.h"
|
||||
#elif defined(STM32F10X_CL)
|
||||
#include "stm32f10x.h"
|
||||
#endif /* STM32F2XX */
|
||||
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_dfu_core.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef struct _DFU_MAL_PROP
|
||||
{
|
||||
const uint8_t* pStrDesc;
|
||||
uint16_t (*pMAL_Init) (void);
|
||||
uint16_t (*pMAL_DeInit) (void);
|
||||
uint16_t (*pMAL_Erase) (uint32_t Add);
|
||||
uint16_t (*pMAL_Write) (uint32_t Add, uint32_t Len);
|
||||
uint8_t *(*pMAL_Read) (uint32_t Add, uint32_t Len);
|
||||
uint16_t (*pMAL_CheckAdd) (uint32_t Add);
|
||||
const uint32_t EraseTiming;
|
||||
const uint32_t WriteTiming;
|
||||
}
|
||||
DFU_MAL_Prop_TypeDef;
|
||||
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define MAL_OK 0
|
||||
#define MAL_FAIL 1
|
||||
|
||||
/* utils macro ---------------------------------------------------------------*/
|
||||
#define _1st_BYTE(x) (uint8_t)((x)&0xFF) /* 1st addressing cycle */
|
||||
#define _2nd_BYTE(x) (uint8_t)(((x)&0xFF00)>>8) /* 2nd addressing cycle */
|
||||
#define _3rd_BYTE(x) (uint8_t)(((x)&0xFF0000)>>16) /* 3rd addressing cycle */
|
||||
#define _4th_BYTE(x) (uint8_t)(((x)&0xFF000000)>>24) /* 4th addressing cycle */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#define SET_POLLING_TIMING(x) buffer[1] = _1st_BYTE(x);\
|
||||
buffer[2] = _2nd_BYTE(x);\
|
||||
buffer[3] = _3rd_BYTE(x);
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
uint16_t MAL_Init (void);
|
||||
uint16_t MAL_DeInit (void);
|
||||
uint16_t MAL_Erase (uint32_t SectorAddress);
|
||||
uint16_t MAL_Write (uint32_t SectorAddress, uint32_t DataLength);
|
||||
uint8_t *MAL_Read (uint32_t SectorAddress, uint32_t DataLength);
|
||||
uint16_t MAL_GetStatus(uint32_t SectorAddress ,uint8_t Cmd, uint8_t *buffer);
|
||||
|
||||
extern uint8_t MAL_Buffer[XFERSIZE]; /* RAM Buffer for Downloaded Data */
|
||||
#endif /* __DFU_MAL_H */
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_flash_if.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0RC1
|
||||
* @date 18-March-2011
|
||||
* @brief Header for usbd_flash_if.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __FLASH_IF_MAL_H
|
||||
#define __FLASH_IF_MAL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_dfu_mal.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define FLASH_START_ADD 0x08000000
|
||||
|
||||
#ifdef STM32F2XX
|
||||
#define FLASH_END_ADD 0x08100000
|
||||
#define FLASH_IF_STRING "@Internal Flash /0x08000000/03*016Ka,01*016Kg,01*064Kg,07*128Kg"
|
||||
#elif defined(STM32F10X_CL)
|
||||
#define FLASH_END_ADD 0x08040000
|
||||
#define FLASH_IF_STRING "@Internal Flash /0x08000000/06*002Ka,122*002Kg"
|
||||
#endif /* STM32F2XX */
|
||||
|
||||
|
||||
extern DFU_MAL_Prop_TypeDef DFU_Flash_cb;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
#endif /* __FLASH_IF_MAL_H */
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_mem_if_template.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief Header for usbd_mem_if_template.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MEM_IF_MAL_H
|
||||
#define __MEM_IF_MAL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#ifdef STM32F2XX
|
||||
#include "stm32f2xx.h"
|
||||
#endif /* STM32F2XX */
|
||||
#include "usbd_dfu_mal.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define MEM_START_ADD 0x00000000 /* Dummy start address */
|
||||
#define MEM_END_ADD (uint32_t)(MEM_START_ADD + (5 * 1024)) /* Dummy Size = 5KB */
|
||||
|
||||
#define MEM_IF_STRING "@Dummy Memory /0x00000000/01*002Kg,03*001Kg"
|
||||
|
||||
extern DFU_MAL_Prop_TypeDef DFU_Mem_cb;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
#endif /* __MEM_IF_MAL_H */
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_otp_if.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief Header for usbd_otp_if.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __OTP_IF_MAL_H
|
||||
#define __OTP_IF_MAL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_dfu_mal.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define OTP_START_ADD 0x1FFF7800
|
||||
#define OTP_END_ADD (uint32_t)(OTP_START_ADD + 528)
|
||||
|
||||
#define OTP_IF_STRING "@OTP Area /0x1FFF7800/01*512 g,01*016 g"
|
||||
|
||||
extern DFU_MAL_Prop_TypeDef DFU_Otp_cb;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
#endif /* __OTP_IF_MAL_H */
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_hid_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_hid_core.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __USB_HID_CORE_H_
|
||||
#define __USB_HID_CORE_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_HID
|
||||
* @brief This file is the Header file for USBD_msc.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USB_HID_CONFIG_DESC_SIZ 34
|
||||
#define USB_HID_DESC_SIZ 9
|
||||
#define HID_MOUSE_REPORT_DESC_SIZE 74
|
||||
|
||||
#define HID_DESCRIPTOR_TYPE 0x21
|
||||
#define HID_REPORT_DESC 0x22
|
||||
|
||||
|
||||
#define HID_REQ_SET_PROTOCOL 0x0B
|
||||
#define HID_REQ_GET_PROTOCOL 0x03
|
||||
|
||||
#define HID_REQ_SET_IDLE 0x0A
|
||||
#define HID_REQ_GET_IDLE 0x02
|
||||
|
||||
#define HID_REQ_SET_REPORT 0x09
|
||||
#define HID_REQ_GET_REPORT 0x01
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern USBD_Class_cb_TypeDef USBD_HID_cb;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
uint8_t USBD_HID_SendReport (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *report,
|
||||
uint16_t len);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __USB_HID_CORE_H_
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_msc_bot.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header for the usbd_msc_bot.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#include "usbd_core.h"
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_MSC_BOT_H
|
||||
#define __USBD_MSC_BOT_H
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup MSC_BOT
|
||||
* @brief This file is the Header file for usbd_bot.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define BOT_IDLE 0 /* Idle state */
|
||||
#define BOT_DATA_OUT 1 /* Data Out state */
|
||||
#define BOT_DATA_IN 2 /* Data In state */
|
||||
#define BOT_LAST_DATA_IN 3 /* Last Data In Last */
|
||||
#define BOT_SEND_DATA 4 /* Send Immediate data */
|
||||
|
||||
#define BOT_CBW_SIGNATURE 0x43425355
|
||||
#define BOT_CSW_SIGNATURE 0x53425355
|
||||
#define BOT_CBW_LENGTH 31
|
||||
#define BOT_CSW_LENGTH 13
|
||||
|
||||
/* CSW Status Definitions */
|
||||
#define CSW_CMD_PASSED 0x00
|
||||
#define CSW_CMD_FAILED 0x01
|
||||
#define CSW_PHASE_ERROR 0x02
|
||||
|
||||
/* BOT Status */
|
||||
#define BOT_STATE_NORMAL 0
|
||||
#define BOT_STATE_RECOVERY 1
|
||||
#define BOT_STATE_ERROR 2
|
||||
|
||||
|
||||
#define DIR_IN 0
|
||||
#define DIR_OUT 1
|
||||
#define BOTH_DIR 2
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup MSC_CORE_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct _MSC_BOT_CBW
|
||||
{
|
||||
uint32_t dSignature;
|
||||
uint32_t dTag;
|
||||
uint32_t dDataLength;
|
||||
uint8_t bmFlags;
|
||||
uint8_t bLUN;
|
||||
uint8_t bCBLength;
|
||||
uint8_t CB[16];
|
||||
}
|
||||
MSC_BOT_CBW_TypeDef;
|
||||
|
||||
|
||||
typedef struct _MSC_BOT_CSW
|
||||
{
|
||||
uint32_t dSignature;
|
||||
uint32_t dTag;
|
||||
uint32_t dDataResidue;
|
||||
uint8_t bStatus;
|
||||
}
|
||||
MSC_BOT_CSW_TypeDef;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern uint8_t MSC_BOT_Data[];
|
||||
extern uint16_t MSC_BOT_DataLen;
|
||||
extern uint8_t MSC_BOT_State;
|
||||
extern uint8_t MSC_BOT_BurstMode;
|
||||
extern MSC_BOT_CBW_TypeDef MSC_BOT_cbw;
|
||||
extern MSC_BOT_CSW_TypeDef MSC_BOT_csw;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/** @defgroup USBD_CORE_Exported_FunctionsPrototypes
|
||||
* @{
|
||||
*/
|
||||
void MSC_BOT_Init (USB_OTG_CORE_HANDLE *pdev);
|
||||
void MSC_BOT_Reset (USB_OTG_CORE_HANDLE *pdev);
|
||||
void MSC_BOT_DeInit (USB_OTG_CORE_HANDLE *pdev);
|
||||
void MSC_BOT_DataIn (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t epnum);
|
||||
|
||||
void MSC_BOT_DataOut (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t epnum);
|
||||
|
||||
void MSC_BOT_SendCSW (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t CSW_Status);
|
||||
|
||||
void MSC_BOT_CplClrFeature (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t epnum);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USBD_MSC_BOT_H */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_msc_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header for the usbd_msc_core.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _USB_MSC_CORE_H_
|
||||
#define _USB_MSC_CORE_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
/** @addtogroup USBD_MSC_BOT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MSC
|
||||
* @brief This file is the Header file for USBD_msc.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_BOT_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#define BOT_GET_MAX_LUN 0xFE
|
||||
#define BOT_RESET 0xFF
|
||||
#define USB_MSC_CONFIG_DESC_SIZ 32
|
||||
|
||||
#define MSC_EPIN_SIZE *(uint16_t *)(((USB_OTG_CORE_HANDLE *)pdev)->dev.pConfig_descriptor + 22)
|
||||
|
||||
#define MSC_EPOUT_SIZE *(uint16_t *)(((USB_OTG_CORE_HANDLE *)pdev)->dev.pConfig_descriptor + 29)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CORE_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern USBD_Class_cb_TypeDef USBD_MSC_cb;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif // _USB_MSC_CORE_H_
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_msc_data.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header for the usbd_msc_data.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef _USBD_MSC_DATA_H_
|
||||
#define _USBD_MSC_DATA_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_conf.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_INFO
|
||||
* @brief general defines for the usb device library file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_INFO_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define MODE_SENSE6_LEN 8
|
||||
#define MODE_SENSE10_LEN 8
|
||||
#define LENGTH_INQUIRY_PAGE00 7
|
||||
#define LENGTH_FORMAT_CAPACITIES 20
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_INFO_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_INFO_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_INFO_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
extern const uint8_t MSC_Page00_Inquiry_Data[];
|
||||
extern const uint8_t MSC_Mode_Sense6_data[];
|
||||
extern const uint8_t MSC_Mode_Sense10_data[] ;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_INFO_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _USBD_MSC_DATA_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_msc_mem.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header for the STORAGE DISK file file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef __USBD_MEM_H
|
||||
#define __USBD_MEM_H
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MEM
|
||||
* @brief header file for the storage disk file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MEM_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USBD_STD_INQUIRY_LENGTH 36
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_MEM_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct _USBD_STORAGE
|
||||
{
|
||||
int8_t (* Init) (uint8_t lun);
|
||||
int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint32_t *block_size);
|
||||
int8_t (* IsReady) (uint8_t lun);
|
||||
int8_t (* IsWriteProtected) (uint8_t lun);
|
||||
int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
|
||||
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
|
||||
int8_t (* GetMaxLun)(void);
|
||||
int8_t *pInquiry;
|
||||
|
||||
}USBD_STORAGE_cb_TypeDef;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_MEM_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MEM_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_MEM_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
extern USBD_STORAGE_cb_TypeDef *USBD_STORAGE_fops;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USBD_MEM_H */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_msc_scsi.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header for the usbd_msc_scsi.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_MSC_SCSI_H
|
||||
#define __USBD_MSC_SCSI_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_SCSI
|
||||
* @brief header file for the storage disk file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_SCSI_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define SENSE_LIST_DEEPTH 4
|
||||
|
||||
/* SCSI Commands */
|
||||
#define SCSI_FORMAT_UNIT 0x04
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_MODE_SELECT6 0x15
|
||||
#define SCSI_MODE_SELECT10 0x55
|
||||
#define SCSI_MODE_SENSE6 0x1A
|
||||
#define SCSI_MODE_SENSE10 0x5A
|
||||
#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E
|
||||
#define SCSI_READ6 0x08
|
||||
#define SCSI_READ10 0x28
|
||||
#define SCSI_READ12 0xA8
|
||||
#define SCSI_READ16 0x88
|
||||
|
||||
#define SCSI_READ_CAPACITY10 0x25
|
||||
#define SCSI_READ_CAPACITY16 0x9E
|
||||
|
||||
#define SCSI_REQUEST_SENSE 0x03
|
||||
#define SCSI_START_STOP_UNIT 0x1B
|
||||
#define SCSI_TEST_UNIT_READY 0x00
|
||||
#define SCSI_WRITE6 0x0A
|
||||
#define SCSI_WRITE10 0x2A
|
||||
#define SCSI_WRITE12 0xAA
|
||||
#define SCSI_WRITE16 0x8A
|
||||
|
||||
#define SCSI_VERIFY10 0x2F
|
||||
#define SCSI_VERIFY12 0xAF
|
||||
#define SCSI_VERIFY16 0x8F
|
||||
|
||||
#define SCSI_SEND_DIAGNOSTIC 0x1D
|
||||
#define SCSI_READ_FORMAT_CAPACITIES 0x23
|
||||
|
||||
#define NO_SENSE 0
|
||||
#define RECOVERED_ERROR 1
|
||||
#define NOT_READY 2
|
||||
#define MEDIUM_ERROR 3
|
||||
#define HARDWARE_ERROR 4
|
||||
#define ILLEGAL_REQUEST 5
|
||||
#define UNIT_ATTENTION 6
|
||||
#define DATA_PROTECT 7
|
||||
#define BLANK_CHECK 8
|
||||
#define VENDOR_SPECIFIC 9
|
||||
#define COPY_ABORTED 10
|
||||
#define ABORTED_COMMAND 11
|
||||
#define VOLUME_OVERFLOW 13
|
||||
#define MISCOMPARE 14
|
||||
|
||||
|
||||
#define INVALID_CDB 0x20
|
||||
#define INVALID_FIELED_IN_COMMAND 0x24
|
||||
#define PARAMETER_LIST_LENGTH_ERROR 0x1A
|
||||
#define INVALID_FIELD_IN_PARAMETER_LIST 0x26
|
||||
#define ADDRESS_OUT_OF_RANGE 0x21
|
||||
#define MEDIUM_NOT_PRESENT 0x3A
|
||||
#define MEDIUM_HAVE_CHANGED 0x28
|
||||
#define WRITE_PROTECTED 0x27
|
||||
#define UNRECOVERED_READ_ERROR 0x11
|
||||
#define WRITE_FAULT 0x03
|
||||
|
||||
#define READ_FORMAT_CAPACITY_DATA_LEN 0x0C
|
||||
#define READ_CAPACITY10_DATA_LEN 0x08
|
||||
#define MODE_SENSE10_DATA_LEN 0x08
|
||||
#define MODE_SENSE6_DATA_LEN 0x04
|
||||
#define REQUEST_SENSE_DATA_LEN 0x12
|
||||
#define STANDARD_INQUIRY_DATA_LEN 0x24
|
||||
#define BLKVFY 0x04
|
||||
|
||||
extern uint8_t Page00_Inquiry_Data[];
|
||||
extern uint8_t Standard_Inquiry_Data[];
|
||||
extern uint8_t Standard_Inquiry_Data2[];
|
||||
extern uint8_t Mode_Sense6_data[];
|
||||
extern uint8_t Mode_Sense10_data[];
|
||||
extern uint8_t Scsi_Sense_Data[];
|
||||
extern uint8_t ReadCapacity10_Data[];
|
||||
extern uint8_t ReadFormatCapacity_Data [];
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_SCSI_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct _SENSE_ITEM {
|
||||
char Skey;
|
||||
union {
|
||||
struct _ASCs {
|
||||
char ASC;
|
||||
char ASCQ;
|
||||
}b;
|
||||
unsigned int ASC;
|
||||
char *pData;
|
||||
} w;
|
||||
} SCSI_Sense_TypeDef;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_SCSI_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_SCSI_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
extern SCSI_Sense_TypeDef SCSI_Sense [SENSE_LIST_DEEPTH];
|
||||
extern uint8_t SCSI_Sense_Head;
|
||||
extern uint8_t SCSI_Sense_Tail;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/** @defgroup USBD_SCSI_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
int8_t SCSI_ProcessCmd(USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t lun,
|
||||
uint8_t *cmd);
|
||||
|
||||
void SCSI_SenseCode(uint8_t lun,
|
||||
uint8_t sKey,
|
||||
uint8_t ASC);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USBD_MSC_SCSI_H */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_conf_template.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief usb device configuration template file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_CONF__H__
|
||||
#define __USBD_CONF__H__
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f2xx.h"
|
||||
|
||||
|
||||
|
||||
/** @defgroup USB_CONF_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USE_USB_OTG_HS
|
||||
|
||||
#define USBD_CFG_MAX_NUM 1
|
||||
#define USB_MAX_STR_DESC_SIZ 64
|
||||
#define USBD_EP0_MAX_PACKET_SIZE 64
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USB_CONF_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USB_CONF_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CONF_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USB_CONF_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif //__USBD_CONF__H__
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief Header file for usbd_core.c
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_CORE_H
|
||||
#define __USBD_CORE_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_dcd.h"
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE
|
||||
* @brief This file is the Header file for usbd_core.c file
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
USBD_OK = 0,
|
||||
USBD_BUSY,
|
||||
USBD_FAIL,
|
||||
}USBD_Status;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
void USBD_Init(USB_OTG_CORE_HANDLE *pdev,
|
||||
USB_OTG_CORE_ID_TypeDef coreID,
|
||||
USBD_DEVICE *pDevice,
|
||||
USBD_Class_cb_TypeDef *class_cb,
|
||||
USBD_Usr_cb_TypeDef *usr_cb);
|
||||
|
||||
USBD_Status USBD_DeInit(USB_OTG_CORE_HANDLE *pdev);
|
||||
|
||||
USBD_Status USBD_DeInitFull(USB_OTG_CORE_HANDLE *pdev);
|
||||
|
||||
USBD_Status USBD_ClrCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx);
|
||||
|
||||
USBD_Status USBD_SetCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USBD_CORE_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_def.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief general defines for the usb device library
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef __USBD_DEF_H
|
||||
#define __USBD_DEF_H
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_conf.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DEF
|
||||
* @brief general defines for the usb device library file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DEF_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#define USB_LEN_DEV_QUALIFIER_DESC 0x0A
|
||||
#define USB_LEN_DEV_DESC 0x12
|
||||
#define USB_LEN_CFG_DESC 0x09
|
||||
#define USB_LEN_IF_DESC 0x09
|
||||
#define USB_LEN_EP_DESC 0x07
|
||||
#define USB_LEN_OTG_DESC 0x03
|
||||
|
||||
#define USBD_IDX_LANGID_STR 0x00
|
||||
#define USBD_IDX_MFC_STR 0x01
|
||||
#define USBD_IDX_PRODUCT_STR 0x02
|
||||
#define USBD_IDX_SERIAL_STR 0x03
|
||||
#define USBD_IDX_CONFIG_STR 0x04
|
||||
#define USBD_IDX_INTERFACE_STR 0x05
|
||||
|
||||
#define USB_REQ_TYPE_STANDARD 0x00
|
||||
#define USB_REQ_TYPE_CLASS 0x20
|
||||
#define USB_REQ_TYPE_VENDOR 0x40
|
||||
#define USB_REQ_TYPE_MASK 0x60
|
||||
|
||||
#define USB_REQ_RECIPIENT_DEVICE 0x00
|
||||
#define USB_REQ_RECIPIENT_INTERFACE 0x01
|
||||
#define USB_REQ_RECIPIENT_ENDPOINT 0x02
|
||||
#define USB_REQ_RECIPIENT_MASK 0x03
|
||||
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
#define USB_DESC_TYPE_DEVICE 1
|
||||
#define USB_DESC_TYPE_CONFIGURATION 2
|
||||
#define USB_DESC_TYPE_STRING 3
|
||||
#define USB_DESC_TYPE_INTERFACE 4
|
||||
#define USB_DESC_TYPE_ENDPOINT 5
|
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
|
||||
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
|
||||
|
||||
|
||||
#define USB_CONFIG_REMOTE_WAKEUP 2
|
||||
#define USB_CONFIG_SELF_POWERED 1
|
||||
|
||||
#define USB_FEATURE_EP_HALT 0
|
||||
#define USB_FEATURE_REMOTE_WAKEUP 1
|
||||
#define USB_FEATURE_TEST_MODE 2
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \
|
||||
(((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8))
|
||||
|
||||
#define LOBYTE(x) ((uint8_t)(x & 0x00FF))
|
||||
#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DEF_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USBD_DEF_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_ioreq.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_ioreq.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef __USBD_IOREQ_H_
|
||||
#define __USBD_IOREQ_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ
|
||||
* @brief header file for the usbd_ioreq.c file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
USBD_Status USBD_CtlSendData (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *buf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_Status USBD_CtlContinueSendData (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_Status USBD_CtlPrepareRx (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_Status USBD_CtlContinueRx (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len);
|
||||
|
||||
USBD_Status USBD_CtlSendStatus (USB_OTG_CORE_HANDLE *pdev);
|
||||
|
||||
USBD_Status USBD_CtlReceiveStatus (USB_OTG_CORE_HANDLE *pdev);
|
||||
|
||||
uint16_t USBD_GetRxCount (USB_OTG_CORE_HANDLE *pdev ,
|
||||
uint8_t epnum);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USBD_IOREQ_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_req.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief header file for the usbd_req.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef __USB_REQUEST_H_
|
||||
#define __USB_REQUEST_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ
|
||||
* @brief header file for the usbd_ioreq.c file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_REQ_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
USBD_Status USBD_StdDevReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req);
|
||||
USBD_Status USBD_StdItfReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req);
|
||||
USBD_Status USBD_StdEPReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req);
|
||||
void USBD_ParseSetupRequest( USB_OTG_CORE_HANDLE *pdev,
|
||||
USB_SETUP_REQ *req);
|
||||
|
||||
void USBD_CtlError( USB_OTG_CORE_HANDLE *pdev,
|
||||
USB_SETUP_REQ *req);
|
||||
|
||||
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __USB_REQUEST_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_usr.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief Header file for usbd_usr.c
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USBD_USR_H__
|
||||
#define __USBD_USR_H__
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_core.h"
|
||||
|
||||
|
||||
/** @addtogroup USBD_USER
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBD_MSC_DEMO_USER_CALLBACKS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_USR
|
||||
* @brief This file is the Header file for usbd_usr.c
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_USR_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern USBD_Usr_cb_TypeDef USR_cb;
|
||||
extern USBD_Usr_cb_TypeDef USR_FS_cb;
|
||||
extern USBD_Usr_cb_TypeDef USR_HS_cb;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_USR_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_USR_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_USR_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
void USBD_USR_Init(void);
|
||||
void USBD_USR_DeviceReset (uint8_t speed);
|
||||
void USBD_USR_DeviceConfigured (void);
|
||||
void USBD_USR_DeviceSuspended(void);
|
||||
void USBD_USR_DeviceResumed(void);
|
||||
|
||||
void USBD_USR_DeviceConnected(void);
|
||||
void USBD_USR_DeviceDisconnected(void);
|
||||
|
||||
void USBD_USR_FS_Init(void);
|
||||
void USBD_USR_FS_DeviceReset (uint8_t speed);
|
||||
void USBD_USR_FS_DeviceConfigured (void);
|
||||
void USBD_USR_FS_DeviceSuspended(void);
|
||||
void USBD_USR_FS_DeviceResumed(void);
|
||||
|
||||
void USBD_USR_FS_DeviceConnected(void);
|
||||
void USBD_USR_FS_DeviceDisconnected(void);
|
||||
|
||||
void USBD_USR_HS_Init(void);
|
||||
void USBD_USR_HS_DeviceReset (uint8_t speed);
|
||||
void USBD_USR_HS_DeviceConfigured (void);
|
||||
void USBD_USR_HS_DeviceSuspended(void);
|
||||
void USBD_USR_HS_DeviceResumed(void);
|
||||
|
||||
void USBD_USR_HS_DeviceConnected(void);
|
||||
void USBD_USR_HS_DeviceDisconnected(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_USR_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /*__USBD_USR_H__*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,483 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_core.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief This file provides all the USBD core functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_req.h"
|
||||
#include "usbd_ioreq.h"
|
||||
#include "usb_dcd_int.h"
|
||||
#include "usb_bsp.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_CORE_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev);
|
||||
static uint8_t USBD_DataOutStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum);
|
||||
static uint8_t USBD_DataInStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum);
|
||||
static uint8_t USBD_SOF(USB_OTG_CORE_HANDLE *pdev);
|
||||
static uint8_t USBD_Reset(USB_OTG_CORE_HANDLE *pdev);
|
||||
static uint8_t USBD_Suspend(USB_OTG_CORE_HANDLE *pdev);
|
||||
static uint8_t USBD_Resume(USB_OTG_CORE_HANDLE *pdev);
|
||||
#ifdef VBUS_SENSING_ENABLED
|
||||
static uint8_t USBD_DevConnected(USB_OTG_CORE_HANDLE *pdev);
|
||||
static uint8_t USBD_DevDisconnected(USB_OTG_CORE_HANDLE *pdev);
|
||||
#endif
|
||||
static uint8_t USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE *pdev);
|
||||
static uint8_t USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE *pdev);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
|
||||
USBD_DCD_INT_cb_TypeDef USBD_DCD_INT_cb =
|
||||
{
|
||||
USBD_DataOutStage,
|
||||
USBD_DataInStage,
|
||||
USBD_SetupStage,
|
||||
USBD_SOF,
|
||||
USBD_Reset,
|
||||
USBD_Suspend,
|
||||
USBD_Resume,
|
||||
USBD_IsoINIncomplete,
|
||||
USBD_IsoOUTIncomplete,
|
||||
#ifdef VBUS_SENSING_ENABLED
|
||||
USBD_DevConnected,
|
||||
USBD_DevDisconnected,
|
||||
#endif
|
||||
};
|
||||
|
||||
USBD_DCD_INT_cb_TypeDef *USBD_DCD_INT_fops = &USBD_DCD_INT_cb;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CORE_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_Init
|
||||
* Initailizes the device stack and load the class driver
|
||||
* @param pdev: device instance
|
||||
* @param core_address: USB OTG core ID
|
||||
* @param class_cb: Class callback structure address
|
||||
* @param usr_cb: User callback structure address
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_Init(USB_OTG_CORE_HANDLE *pdev,
|
||||
USB_OTG_CORE_ID_TypeDef coreID,
|
||||
USBD_DEVICE *pDevice,
|
||||
USBD_Class_cb_TypeDef *class_cb,
|
||||
USBD_Usr_cb_TypeDef *usr_cb)
|
||||
{
|
||||
/* Hardware Init */
|
||||
USB_OTG_BSP_Init(pdev);
|
||||
|
||||
USBD_DeInit(pdev);
|
||||
|
||||
/*Register class and user callbacks */
|
||||
pdev->dev.class_cb = class_cb;
|
||||
pdev->dev.usr_cb = usr_cb;
|
||||
pdev->dev.usr_device = pDevice;
|
||||
|
||||
/* set USB OTG core params */
|
||||
DCD_Init(pdev , coreID);
|
||||
|
||||
/* Upon Init call usr callback */
|
||||
pdev->dev.usr_cb->Init();
|
||||
|
||||
/* Enable Interrupts */
|
||||
USB_OTG_BSP_EnableInterrupt(pdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DeInit
|
||||
* Re-Initialize th deviuce library
|
||||
* @param pdev: device instance
|
||||
* @retval status: status
|
||||
*/
|
||||
USBD_Status USBD_DeInit(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
USBD_Status USBD_DeInitFull(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
/* Software Init */
|
||||
USB_OTG_BSP_DisableInterrupt(pdev);
|
||||
USB_OTG_BSP_DeInit(pdev);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_SetupStage
|
||||
* Handle the setup stage
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
USB_SETUP_REQ req;
|
||||
|
||||
USBD_ParseSetupRequest(pdev , &req);
|
||||
|
||||
switch (req.bmRequest & 0x1F)
|
||||
{
|
||||
case USB_REQ_RECIPIENT_DEVICE:
|
||||
USBD_StdDevReq (pdev, &req);
|
||||
break;
|
||||
|
||||
case USB_REQ_RECIPIENT_INTERFACE:
|
||||
USBD_StdItfReq(pdev, &req);
|
||||
break;
|
||||
|
||||
case USB_REQ_RECIPIENT_ENDPOINT:
|
||||
USBD_StdEPReq(pdev, &req);
|
||||
break;
|
||||
|
||||
default:
|
||||
DCD_EP_Stall(pdev , req.bmRequest & 0x80);
|
||||
break;
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DataOutStage
|
||||
* Handle data out stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_DataOutStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
|
||||
{
|
||||
USB_OTG_EP *ep;
|
||||
|
||||
if(epnum == 0)
|
||||
{
|
||||
ep = &pdev->dev.out_ep[0];
|
||||
if ( pdev->dev.device_state == USB_OTG_EP0_DATA_OUT)
|
||||
{
|
||||
if(ep->rem_data_len > ep->maxpacket)
|
||||
{
|
||||
ep->rem_data_len -= ep->maxpacket;
|
||||
|
||||
if(pdev->cfg.dma_enable == 1)
|
||||
{
|
||||
/* in slave mode this, is handled by the RxSTSQLvl ISR */
|
||||
ep->xfer_buff += ep->maxpacket;
|
||||
}
|
||||
USBD_CtlContinueRx (pdev,
|
||||
ep->xfer_buff,
|
||||
MIN(ep->rem_data_len ,ep->maxpacket));
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pdev->dev.class_cb->EP0_RxReady != NULL)&&
|
||||
(pdev->dev.device_status == USB_OTG_CONFIGURED))
|
||||
{
|
||||
pdev->dev.class_cb->EP0_RxReady(pdev);
|
||||
}
|
||||
USBD_CtlSendStatus(pdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((pdev->dev.class_cb->DataOut != NULL)&&
|
||||
(pdev->dev.device_status == USB_OTG_CONFIGURED))
|
||||
{
|
||||
pdev->dev.class_cb->DataOut(pdev, epnum);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DataInStage
|
||||
* Handle data in stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_DataInStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
|
||||
{
|
||||
USB_OTG_EP *ep;
|
||||
|
||||
if(epnum == 0)
|
||||
{
|
||||
ep = &pdev->dev.in_ep[0];
|
||||
if ( pdev->dev.device_state == USB_OTG_EP0_DATA_IN)
|
||||
{
|
||||
if(ep->rem_data_len > ep->maxpacket)
|
||||
{
|
||||
ep->rem_data_len -= ep->maxpacket;
|
||||
if(pdev->cfg.dma_enable == 1)
|
||||
{
|
||||
/* in slave mode this, is handled by the TxFifoEmpty ISR */
|
||||
ep->xfer_buff += ep->maxpacket;
|
||||
}
|
||||
USBD_CtlContinueSendData (pdev,
|
||||
ep->xfer_buff,
|
||||
ep->rem_data_len);
|
||||
}
|
||||
else
|
||||
{ /* last packet is MPS multiple, so send ZLP packet */
|
||||
if((ep->total_data_len % ep->maxpacket == 0) &&
|
||||
(ep->total_data_len >= ep->maxpacket) &&
|
||||
(ep->total_data_len < ep->ctl_data_len ))
|
||||
{
|
||||
|
||||
USBD_CtlContinueSendData(pdev , NULL, 0);
|
||||
ep->ctl_data_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pdev->dev.class_cb->EP0_TxSent != NULL)&&
|
||||
(pdev->dev.device_status == USB_OTG_CONFIGURED))
|
||||
{
|
||||
pdev->dev.class_cb->EP0_TxSent(pdev);
|
||||
}
|
||||
USBD_CtlReceiveStatus(pdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((pdev->dev.class_cb->DataIn != NULL)&&
|
||||
(pdev->dev.device_status == USB_OTG_CONFIGURED))
|
||||
{
|
||||
pdev->dev.class_cb->DataIn(pdev, epnum);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_Reset
|
||||
* Handle Reset event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
static uint8_t USBD_Reset(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
/* Open EP0 OUT */
|
||||
DCD_EP_Open(pdev,
|
||||
0x00,
|
||||
USB_OTG_MAX_EP0_SIZE,
|
||||
EP_TYPE_CTRL);
|
||||
|
||||
/* Open EP0 IN */
|
||||
DCD_EP_Open(pdev,
|
||||
0x80,
|
||||
USB_OTG_MAX_EP0_SIZE,
|
||||
EP_TYPE_CTRL);
|
||||
|
||||
/* Upon Reset call usr call back */
|
||||
pdev->dev.device_status = USB_OTG_DEFAULT;
|
||||
pdev->dev.usr_cb->DeviceReset(pdev->cfg.speed);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_Resume
|
||||
* Handle Resume event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
static uint8_t USBD_Resume(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
/* Upon Resume call usr call back */
|
||||
pdev->dev.usr_cb->DeviceResumed();
|
||||
pdev->dev.device_status = USB_OTG_CONFIGURED;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_Suspend
|
||||
* Handle Suspend event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
static uint8_t USBD_Suspend(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
|
||||
pdev->dev.device_status = USB_OTG_SUSPENDED;
|
||||
/* Upon Resume call usr call back */
|
||||
pdev->dev.usr_cb->DeviceSuspended();
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_SOF
|
||||
* Handle SOF event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
static uint8_t USBD_SOF(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
if(pdev->dev.class_cb->SOF)
|
||||
{
|
||||
pdev->dev.class_cb->SOF(pdev);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
/**
|
||||
* @brief USBD_SetCfg
|
||||
* Configure device and start the interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: configuration index
|
||||
* @retval status
|
||||
*/
|
||||
|
||||
USBD_Status USBD_SetCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx)
|
||||
{
|
||||
pdev->dev.class_cb->Init(pdev, cfgidx);
|
||||
|
||||
/* Upon set config call usr call back */
|
||||
pdev->dev.usr_cb->DeviceConfigured();
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_ClrCfg
|
||||
* Clear current configuration
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: configuration index
|
||||
* @retval status: USBD_Status
|
||||
*/
|
||||
USBD_Status USBD_ClrCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx)
|
||||
{
|
||||
pdev->dev.class_cb->DeInit(pdev, cfgidx);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_IsoINIncomplete
|
||||
* Handle iso in incomplete event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
pdev->dev.class_cb->IsoINIncomplete(pdev);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_IsoOUTIncomplete
|
||||
* Handle iso out incomplete event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
pdev->dev.class_cb->IsoOUTIncomplete(pdev);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
#ifdef VBUS_SENSING_ENABLED
|
||||
/**
|
||||
* @brief USBD_DevConnected
|
||||
* Handle device connection event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_DevConnected(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
pdev->dev.usr_cb->DeviceConnected();
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_DevDisconnected
|
||||
* Handle device disconnection event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_DevDisconnected(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
pdev->dev.usr_cb->DeviceDisconnected();
|
||||
pdev->dev.class_cb->DeInit(pdev, 0);
|
||||
return USBD_OK;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usbd_ioreq.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 22-July-2011
|
||||
* @brief This file provides the IO requests APIs for control endpoints.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_ioreq.h"
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ
|
||||
* @brief control I/O requests module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_IOREQ_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlSendData
|
||||
* send data on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be sent
|
||||
* @retval status
|
||||
*/
|
||||
USBD_Status USBD_CtlSendData (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
USBD_Status ret = USBD_OK;
|
||||
|
||||
pdev->dev.in_ep[0].total_data_len = len;
|
||||
pdev->dev.in_ep[0].rem_data_len = len;
|
||||
pdev->dev.device_state = USB_OTG_EP0_DATA_IN;
|
||||
|
||||
DCD_EP_Tx (pdev, 0, pbuf, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlContinueSendData
|
||||
* continue sending data on the ctl pipe
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be sent
|
||||
* @retval status
|
||||
*/
|
||||
USBD_Status USBD_CtlContinueSendData (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
USBD_Status ret = USBD_OK;
|
||||
|
||||
DCD_EP_Tx (pdev, 0, pbuf, len);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlPrepareRx
|
||||
* receive data on the ctl pipe
|
||||
* @param pdev: USB OTG device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be received
|
||||
* @retval status
|
||||
*/
|
||||
USBD_Status USBD_CtlPrepareRx (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
USBD_Status ret = USBD_OK;
|
||||
|
||||
pdev->dev.out_ep[0].total_data_len = len;
|
||||
pdev->dev.out_ep[0].rem_data_len = len;
|
||||
pdev->dev.device_state = USB_OTG_EP0_DATA_OUT;
|
||||
|
||||
DCD_EP_PrepareRx (pdev,
|
||||
0,
|
||||
pbuf,
|
||||
len);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlContinueRx
|
||||
* continue receive data on the ctl pipe
|
||||
* @param pdev: USB OTG device instance
|
||||
* @param buff: pointer to data buffer
|
||||
* @param len: length of data to be received
|
||||
* @retval status
|
||||
*/
|
||||
USBD_Status USBD_CtlContinueRx (USB_OTG_CORE_HANDLE *pdev,
|
||||
uint8_t *pbuf,
|
||||
uint16_t len)
|
||||
{
|
||||
USBD_Status ret = USBD_OK;
|
||||
|
||||
DCD_EP_PrepareRx (pdev,
|
||||
0,
|
||||
pbuf,
|
||||
len);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief USBD_CtlSendStatus
|
||||
* send zero lzngth packet on the ctl pipe
|
||||
* @param pdev: USB OTG device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_Status USBD_CtlSendStatus (USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
USBD_Status ret = USBD_OK;
|
||||
pdev->dev.device_state = USB_OTG_EP0_STATUS_IN;
|
||||
DCD_EP_Tx (pdev,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
USB_OTG_EP0_OutStart(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CtlReceiveStatus
|
||||
* receive zero lzngth packet on the ctl pipe
|
||||
* @param pdev: USB OTG device instance
|
||||
* @retval status
|
||||
*/
|
||||
USBD_Status USBD_CtlReceiveStatus (USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
USBD_Status ret = USBD_OK;
|
||||
pdev->dev.device_state = USB_OTG_EP0_STATUS_OUT;
|
||||
DCD_EP_PrepareRx ( pdev,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
USB_OTG_EP0_OutStart(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_GetRxCount
|
||||
* returns the received data length
|
||||
* @param pdev: USB OTG device instance
|
||||
* epnum: endpoint index
|
||||
* @retval Rx Data blength
|
||||
*/
|
||||
uint16_t USBD_GetRxCount (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
|
||||
{
|
||||
return pdev->dev.out_ep[epnum].xfer_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue