Initial support for STM32F4 series, based on AeroQuad codebase. Board variant for STM32F4 discovery (F407VG). Runs blinky!

This commit is contained in:
Bob Cousins 2014-12-28 14:29:08 +00:00
parent db7e9ee191
commit a5414bb548
160 changed files with 36575 additions and 0 deletions

33
STM32F4/boards.txt Normal file
View File

@ -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
##############################################################

View File

@ -0,0 +1,4 @@
#ifndef Arduino_h
#define Arduino_h
#include "WProgram.h"
#endif

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();

View File

@ -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_ */

View File

@ -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"

View File

@ -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);
}

View File

@ -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

View File

@ -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)
;
}

View File

@ -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;
}

View File

@ -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

222
STM32F4/cores/maple/io.h Normal file
View File

@ -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

View File

@ -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]);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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_ */

View File

@ -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
}

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = &regs->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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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)
*/

View File

@ -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

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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&currentviews=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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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