push the generic_f4 branch to master

This commit is contained in:
stevstrong 2017-05-13 10:27:33 +02:00
parent ff53626018
commit 97329efca3
118 changed files with 2581 additions and 4111 deletions

View File

@ -391,11 +391,11 @@ uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length
spi_rx_dma_enable(_currentSetting->spi_d);
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size,
receiveBuf, dma_bit_size, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA
receiveBuf, dma_bit_size, (DMA_MINC_MODE));// receive buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length);
// TX
uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT);
uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM);
spi_tx_dma_enable(_currentSetting->spi_d);
if ( transmitBuf==0 ) {
static uint8_t ff = 0XFF;
@ -407,13 +407,13 @@ uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
uint32_t m = millis();
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) {//Avoid interrupts and just loop waiting for the flag to be set.
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
@ -443,14 +443,13 @@ uint8 SPIClass::dmaSend(void * transmitBuf, uint16 length, bool minc)
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size,
transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
// while (dma1_ch3_Active);
uint32_t m = millis();
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) {//Avoid interrupts and just loop waiting for the flag to be set.
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."

View File

@ -1,5 +1,7 @@
#
menu.usb_cfg=USB configuration
##############################################################
discovery_f407.name=STM32 Discovery F407
@ -29,6 +31,49 @@ discovery_f407.build.error_led_port=GPIOD
discovery_f407.build.error_led_pin=14
discovery_f407.build.board=STM32DiscoveryF407
discovery_f407.menu.usb_cfg.usb_nc=USB inactive
discovery_f407.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC
discovery_f407.menu.usb_cfg.usb_serial=USB serial (CDC)
discovery_f407.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB
discovery_f407.menu.usb_cfg.usb_msc=USB Mass Storage (MSC)
discovery_f407.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC
##############################################################
generic_f407v.name=Generic STM32F407V series
generic_f407v.upload.tool=stlink_upload
generic_f407v.upload.protocol=stlink
generic_f407v.upload.file_type=bin
generic_f407v.upload.ram.maximum_size=131072
generic_f407v.upload.flash.maximum_size=514288
generic_f407v.upload.maximum_size=514288
#generic_f407v.upload.usbID=0483:3748
#generic_f407v.upload.altID=1
#generic_f407v.upload.auto_reset=true
generic_f407v.build.mcu=cortex-m4
generic_f407v.build.f_cpu=168000000L
generic_f407v.build.core=maple
generic_f407v.build.extra_flags=-mthumb -DSTM32_HIGH_DENSITY -DSTM32F4 -DBOARD_generic_f407v
generic_f407v.build.ldscript=ld/jtag.ld
generic_f407v.build.variant=generic_f407v
generic_f407v.build.variant_system_lib=lib_f407.a
generic_f407v.build.vect=VECT_TAB_BASE
generic_f407v.build.density=STM32_HIGH_DENSITY
generic_f407v.build.error_led_port=GPIOA
generic_f407v.build.error_led_pin=7
generic_f407v.build.board=STM32GenericF407VET6
generic_f407v.menu.usb_cfg.usb_nc=USB inactive
generic_f407v.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC
generic_f407v.menu.usb_cfg.usb_serial=USB serial (CDC)
generic_f407v.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB
generic_f407v.menu.usb_cfg.usb_msc=USB Mass Storage (MSC)
generic_f407v.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC
##############################################################
stm32f4stamp.name=STM32F4Stamp F405
@ -49,7 +94,7 @@ stm32f4stamp.upload.dfuse_addr=0x8000000
stm32f4stamp.build.mcu=cortex-m4
stm32f4stamp.build.f_cpu=168000000L
stm32f4stamp.build.core=maple
stm32f4stamp.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F2 -DSTM32F4 -DBOARD_discovery_f4
stm32f4stamp.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F4 -DBOARD_discovery_f4
stm32f4stamp.build.ldscript=ld/jtag.ld
stm32f4stamp.build.variant=discovery_f407
stm32f4stamp.build.variant_system_lib=lib_f407.a
@ -59,6 +104,12 @@ stm32f4stamp.build.error_led_port=GPIOD
stm32f4stamp.build.error_led_pin=14
stm32f4stamp.build.board=STM32F4StampF405
stm32f4stamp.menu.usb_cfg.usb_nc=USB inactive
stm32f4stamp.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC
stm32f4stamp.menu.usb_cfg.usb_serial=USB serial (CDC)
stm32f4stamp.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB
stm32f4stamp.menu.usb_cfg.usb_msc=USB Mass Storage (MSC)
stm32f4stamp.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC
##############################################################
netduino2plus.name=Netduino2 F405
@ -79,7 +130,7 @@ netduino2plus.upload.dfuse_addr=0x8000000
netduino2plus.build.mcu=cortex-m4
netduino2plus.build.f_cpu=168000000L
netduino2plus.build.core=maple
netduino2plus.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F2 -DSTM32F4 -DBOARD_discovery_f4 -DARDUINO_STM32F4_NETDUINO2PLUS
netduino2plus.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F4 -DBOARD_discovery_f4 -DARDUINO_STM32F4_NETDUINO2PLUS
netduino2plus.build.ldscript=ld/jtag.ld
netduino2plus.build.variant=discovery_f407
netduino2plus.build.variant_system_lib=lib_f407.a
@ -89,5 +140,11 @@ netduino2plus.build.error_led_port=GPIOD
netduino2plus.build.error_led_pin=14
netduino2plus.build.board=Netduino2F405
netduino2plus.menu.usb_cfg.usb_nc=USB inactive
netduino2plus.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC
netduino2plus.menu.usb_cfg.usb_serial=USB serial (CDC)
netduino2plus.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB
netduino2plus.menu.usb_cfg.usb_msc=USB Mass Storage (MSC)
netduino2plus.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC
##############################################################

View File

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

View File

@ -17,8 +17,9 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef client_h
#define client_h
#ifndef _CLIENT_H_
#define _CLIENT_H_
#include "Print.h"
#include "Stream.h"
#include "IPAddress.h"

View File

@ -33,7 +33,7 @@
// TODO [0.1.0] Remove deprecated pieces, pick a better API
#include "timer.h"
#include <libmaple/timer.h>
/** Timer mode. */
typedef timer_mode TimerMode;

View File

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef IPAddress_h
#define IPAddress_h
#ifndef _IPAddress_h_
#define _IPAddress_h_
#include <stdint.h>
#include <WString.h>

View File

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef server_h
#define server_h
#ifndef _SERVER_H_
#define _SERVER_H_
#include "Print.h"

View File

@ -19,8 +19,8 @@
parsing functions based on TextFinder library by Michael Margolis
*/
#ifndef Stream_h
#define Stream_h
#ifndef _STREAM_H_
#define _STREAM_H_
#include <inttypes.h>
#include "Print.h"

View File

@ -32,8 +32,8 @@
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef udp_h
#define udp_h
#ifndef _UDP_H_
#define _UDP_H_
#include <Stream.h>
#include <IPAddress.h>

View File

@ -24,7 +24,12 @@
* SOFTWARE.
*****************************************************************************/
#include "wirish.h"
#ifndef _WPROGRAM_H_
#define _WPROGRAM_H_
#include <wirish.h>
void setup();
void loop();
#endif

View File

@ -19,8 +19,9 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef String_class_h
#define String_class_h
#ifndef _WSTRING_H_
#define _WSTRING_H_
#ifdef __cplusplus
#include <stdlib.h>
@ -225,4 +226,4 @@ public:
};
#endif // __cplusplus
#endif // String_class_h
#endif // _WSTRING_H_

View File

@ -27,4 +27,9 @@
/* Note: Use of this header file is deprecated. Use bit_constants.h
instead. */
#ifndef _BITS_H_
#define _BITS_H_
#include "bit_constants.h"
#endif

View File

@ -33,17 +33,16 @@
*/
#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 <libmaple/flash.h>
#include <libmaple/rcc.h>
#include <libmaple/nvic.h>
#include <libmaple/systick.h>
#include <libmaple/gpio.h>
#include <libmaple/adc.h>
#include <libmaple/timer.h>
#include "usb.h"
#ifdef STM32F2
//#include "usbF4.h"
#endif
#include "usb_serial.h"
static void setupFlash(void);
static void setupClocks(void);
@ -59,7 +58,7 @@ void init(void) {
systick_init(SYSTICK_RELOAD_VAL);
gpio_init_all();
#ifdef STM32F2
#ifdef STM32F4
rcc_clk_enable(RCC_SYSCFG);
#else
afio_init();
@ -69,7 +68,10 @@ void init(void) {
setupADC();
setupTimers();
//setupUSB();
#ifdef SERIAL_USB
setupUSB();
SerialUSB.begin();
#endif
}
/* You could farm this out to the files in boards/ if e.g. it takes
@ -84,11 +86,13 @@ bool boardUsesPin(uint8 pin) {
}
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
*/
}
/*
@ -121,8 +125,8 @@ static void setupNVIC() {
static void adcDefaultConfig(const adc_dev* dev);
static void setupADC() {
#ifdef STM32F2
setupADC_F2();
#ifdef STM32F4
setupADC_F4();
#else
rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6);
#endif

View File

@ -39,11 +39,8 @@
#ifndef _BOARDS_H_
#define _BOARDS_H_
#include "libmaple.h"
#include "gpio.h"
#include "timer.h"
#include "wirish_types.h"
#include <wirish_types.h>
#include <stdbool.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
@ -55,9 +52,12 @@ enum {
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,
#if 0 // not available on LQFP100 package
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, };
D106, D107, D108, D109, D110, D111,
#endif // not available on LQFP100 package
};
/**
* @brief Maps each Maple pin to a corresponding stm32_pin_info.
@ -115,31 +115,20 @@ extern void boardInit(void);
* @return true if the given pin is in boardUsedPins, and false otherwise.
* @see boardUsedPins
*/
bool boardUsesPin(uint8 pin);
extern 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)
#if 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_generic_f407v)
#include "generic_f407v.h"
#elif defined(BOARD_freeflight)
#include "freeflight.h"
#else
@ -160,4 +149,12 @@ bool boardUsesPin(uint8 pin);
#define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND
#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL)
#ifndef SYSTICK_RELOAD_VAL
#define SYSTICK_RELOAD_VAL (1000 * CYCLES_PER_MICROSECOND - 1)
#endif
#ifndef BOARD_BUTTON_PRESSED_LEVEL
#define BOARD_BUTTON_PRESSED_LEVEL HIGH
#endif
#endif

View File

@ -31,8 +31,8 @@
*/
#include "boards.h"
#include "gpio.h"
#include "exti.h"
#include <libmaple/gpio.h>
#include <libmaple/exti.h>
#include "ext_interrupts.h"
static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode);
@ -51,7 +51,7 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) {
exti_trigger_mode outMode = exti_out_mode(mode);
exti_attach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit),
exti_attach_interrupt((afio_exti_num)(pin&0x0F),
gpio_exti_port(PIN_MAP[pin].gpio_device),
handler,
outMode);
@ -66,7 +66,7 @@ void detachInterrupt(uint8 pin) {
return;
}
exti_detach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit));
exti_detach_interrupt((afio_exti_num)(pin&0x0F));
}
static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) {

View File

@ -24,8 +24,8 @@
* SOFTWARE.
*****************************************************************************/
#include "libmaple_types.h"
#include "nvic.h"
#ifndef _EXT_INTERRUPTS_H_
#define _EXT_INTERRUPTS_H_
/**
* @file ext_interrupts.h
@ -33,8 +33,9 @@
* @brief Wiring-like external interrupt prototypes and types.
*/
#ifndef _EXT_INTERRUPTS_H_
#define _EXT_INTERRUPTS_H_
#include <libmaple/libmaple_types.h>
#include <libmaple/nvic.h>
/**
* The kind of transition on an external pin which should trigger an

View File

@ -33,8 +33,9 @@
#ifndef _IO_H_
#define _IO_H_
#include "gpio.h"
#include "adc.h"
#include <inttypes.h>
#include <libmaple/gpio.h>
#include <libmaple/adc.h>
#include "wirish_time.h"
@ -179,9 +180,11 @@ static inline void toggleLED() {
* accomplished portably over all LeafLabs boards by calling
* pinMode(BOARD_BUTTON_PIN, INPUT).
*
* @param button - one of available on-board buttons (up to 3 for generic F4)
*
* @see pinMode()
*/
uint8 isButtonPressed();
uint8 isButtonPressed(uint8_t button);
/**
* Wait until the button is pressed and released, timing out if no
@ -195,12 +198,14 @@ uint8 isButtonPressed();
* button is pressed. If timeout_millis is left out (or 0), wait
* forever.
*
* @param button - one of available on-board buttons (up to 3 for generic F4)
*
* @return true, if the button was pressed; false, if the timeout was
* reached.
*
* @see pinMode()
*/
uint8 waitForButtonPress(uint32 timeout_millis=0);
uint8 waitForButtonPress(uint8_t button, uint32 timeout_millis=0);
/**
* Shift out a byte of data, one bit at a time.

View File

@ -16,8 +16,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ITOA_
#define _ITOA_
#ifndef _ITOA_H_
#define _ITOA_H_
#ifdef __cplusplus
extern "C"{

View File

@ -1,424 +0,0 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @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_SPI3B_NSS_PIN,
BOARD_SPI3B_SCK_PIN,
BOARD_SPI3B_MISO_PIN,
BOARD_SPI3B_MOSI_PIN},
#endif
#ifdef STM32F4
{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 STM32F4
// 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::beginTransaction(uint8_t pin, SPISettings settings)
{
// this->begin(settings.clock, settings.bitOrder, settings.dataMode);
this->begin(SPI_1_125MHZ, settings.bitOrder, settings.dataMode);
}
*/
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 STM32F4
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 STM32F4
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);
} 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);
}
#endif
if(nssi) {
spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit,
scki->gpio_device, scki->gpio_bit,
misoi->gpio_device, misoi->gpio_bit,
mosii->gpio_device, mosii->gpio_bit);
} else {
spi_config_gpios(dev, as_master, NULL, -1,
scki->gpio_device, scki->gpio_bit,
misoi->gpio_device, misoi->gpio_bit,
mosii->gpio_device, 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

@ -1,279 +0,0 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @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"
#include "wirish.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
//#define BOARD_SPI_DEFAULT_SS PC13
#define BOARD_SPI_DEFAULT_SS PB0
#define SPI_MODE0 SPI_MODE_0
#define SPI_MODE1 SPI_MODE_1
#define SPI_MODE2 SPI_MODE_2
#define SPI_MODE3 SPI_MODE_3
/*
class SPISettings {
public:
SPISettings(uint32 clock, BitOrder bitOrder, uint8 dataMode) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode);
} else {
init_MightInline(clock, bitOrder, dataMode);
}
}
SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); }
private:
void init_MightInline(uint32 clock, BitOrder bitOrder, uint8 dataMode) {
init_AlwaysInline(clock, bitOrder, dataMode);
}
void init_AlwaysInline(uint32 clock, BitOrder bitOrder, uint8 dataMode) __attribute__((__always_inline__)) {
this->clock = clock;
this->bitOrder = bitOrder;
this->dataMode = dataMode;
}
uint32 clock;
BitOrder bitOrder;
uint8 dataMode;
friend class HardwareSPI;
};
*/
/**
* @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);
// void beginTransaction(SPISettings settings) { beginTransaction(BOARD_SPI_DEFAULT_SS, settings); }
// void beginTransaction(uint8 pin, SPISettings settings);
void endTransaction(void) { }
private:
spi_dev *spi_d;
};
extern HardwareSPI SPI;
#endif

View File

@ -56,19 +56,19 @@
#define RX5 BOARD_UART5_RX_PIN
#endif
HardwareSerial Serial(USART1, TX1, RX1);
HardwareSerial Serial1(USART1, TX1, RX1);
#ifdef TX2
HardwareSerial Serial1(USART2, TX2, RX2);
HardwareSerial Serial2(USART2, TX2, RX2);
#endif
#ifdef TX3
HardwareSerial Serial2(USART3, TX3, RX3);
HardwareSerial Serial3(USART3, TX3, RX3);
#endif
#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6)
HardwareSerial Serial3(UART4, TX4, RX4);
HardwareSerial Serial4(UART5, TX5, RX5);
HardwareSerial Serial4(UART4, TX4, RX4);
HardwareSerial Serial5(UART5, TX5, RX5);
#endif
HardwareSerial::HardwareSerial(usart_dev *usart_device,
@ -90,25 +90,23 @@ void HardwareSerial::begin(uint32 baud) {
return;
}
const stm32_pin_info *txi = &PIN_MAP[tx_pin];
const stm32_pin_info *rxi = &PIN_MAP[rx_pin];
#ifdef STM32F2
#ifdef STM32F4
// int af = 7<<8;
if (usart_device == UART4 || usart_device == UART5) {
gpio_set_af_mode(txi->gpio_device, txi->gpio_bit, 8);
gpio_set_af_mode(rxi->gpio_device, rxi->gpio_bit, 8);
gpio_set_af_mode(tx_pin, 8);
gpio_set_af_mode(rx_pin, 8);
}
else {
gpio_set_af_mode(txi->gpio_device, txi->gpio_bit, 7);
gpio_set_af_mode(rxi->gpio_device, rxi->gpio_bit, 7);
gpio_set_af_mode(tx_pin, 7);
gpio_set_af_mode(rx_pin, 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(tx_pin, (gpio_pin_mode)(GPIO_AF_OUTPUT_PP | GPIO_PUPD_INPUT_PU | 0x700));
gpio_set_mode(rx_pin, (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);
gpio_set_mode(tx_pin, GPIO_AF_OUTPUT_PP);
gpio_set_mode(rx_pin, GPIO_INPUT_FLOATING);
#endif
#if 0
if (txi->timer_device != NULL) {

View File

@ -75,12 +75,12 @@ private:
uint8 rx_pin;
};
extern HardwareSerial Serial;
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6)
extern HardwareSerial Serial3;
extern HardwareSerial Serial4;
extern HardwareSerial Serial5;
#endif
extern HardwareSerial &SerialDebug;
#endif

View File

@ -41,27 +41,24 @@
#include "rcc.h"
#include "adc.h"
static adc_dev adc1 = {
/** ADC1 device. */
const adc_dev ADC1 = {
.regs = ADC1_BASE,
.clk_id = RCC_ADC1
};
/** ADC1 device. */
const adc_dev *ADC1 = &adc1;
static adc_dev adc2 = {
/** ADC2 device. */
const adc_dev ADC2 = {
.regs = ADC2_BASE,
.clk_id = RCC_ADC2
};
/** ADC2 device. */
const adc_dev *ADC2 = &adc2;
#ifdef STM32_HIGH_DENSITY
adc_dev adc3 = {
/** ADC3 device. */
const adc_dev ADC3 = {
.regs = ADC3_BASE,
.clk_id = RCC_ADC3
};
/** ADC3 device. */
const adc_dev *ADC3 = &adc3;
#endif
/**
@ -74,7 +71,7 @@ const adc_dev *ADC3 = &adc3;
*/
void adc_init(const adc_dev *dev) {
rcc_clk_enable(dev->clk_id);
#ifdef STM32F2
#ifdef STM32F4
if(dev->clk_id == RCC_ADC1) {
rcc_reset_dev(dev->clk_id);
}
@ -101,10 +98,10 @@ void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) {
* @param fn Function to call on each ADC device.
*/
void adc_foreach(void (*fn)(const adc_dev*)) {
fn(ADC1);
fn(ADC2);
fn(&ADC1);
fn(&ADC2);
#ifdef STM32_HIGH_DENSITY
fn(ADC3);
fn(&ADC3);
#endif
}
@ -136,7 +133,9 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) {
* @brief Calibrate an ADC peripheral
* @param dev adc device
*/
void adc_calibrate(const adc_dev *dev) {
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);
@ -149,6 +148,7 @@ void adc_calibrate(const adc_dev *dev) {
while (*cal_bit)
;
#endif
*/
}
/**
@ -171,8 +171,8 @@ uint16 adc_read(const adc_dev *dev, uint8 channel) {
return (uint16)(regs->DR & ADC_DR_DATA);
}
void setupADC_F2() {
#ifdef STM32F2
void setupADC_F4(void)
{
uint32 tmpreg1 = 0;
tmpreg1 = ADC_COMMON->CCR;
@ -196,5 +196,4 @@ void setupADC_F2() {
/* Write to ADC CCR */
ADC_COMMON->CCR = tmpreg1;
#endif
}

View File

@ -42,17 +42,15 @@ 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;
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 {
@ -84,33 +82,22 @@ typedef struct adc_dev {
rcc_clk_id clk_id; /**< RCC clock information */
} adc_dev;
extern const adc_dev *ADC1;
extern const adc_dev *ADC2;
extern const adc_dev ADC1;
extern const adc_dev ADC2;
#ifdef STM32_HIGH_DENSITY
extern const adc_dev *ADC3;
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
/** 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)
/*
* Register bit definitions
@ -167,17 +154,10 @@ extern const adc_dev *ADC3;
#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
@ -388,7 +368,7 @@ static inline void adc_disable_all(void) {
adc_foreach(adc_disable);
}
void setupADC_F2();
extern void setupADC_F4(void);
#ifdef __cplusplus
} // extern "C"

View File

@ -126,11 +126,11 @@ void dac_enable_channel(const dac_dev *dev, uint8 channel) {
*/
switch (channel) {
case 1:
gpio_set_mode(GPIOA, 4, GPIO_INPUT_ANALOG);
gpio_set_mode((uint8_t)PA4, GPIO_INPUT_ANALOG);
dev->regs->CR |= DAC_CR_EN1;
break;
case 2:
gpio_set_mode(GPIOA, 5, GPIO_INPUT_ANALOG);
gpio_set_mode((uint8_t)PA5, GPIO_INPUT_ANALOG);
dev->regs->CR |= DAC_CR_EN2;
break;
}

View File

@ -30,9 +30,4 @@
* @brief Direct Memory Access peripheral support
*/
#ifdef STM32F2
#include "dmaF2.h"
#include <libmaple/dma_common.h>
#else
#include "dmaF1.h"
#endif
#include "dmaF4.h"

View File

@ -1,383 +0,0 @@
/******************************************************************************
* 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

@ -1,453 +0,0 @@
/******************************************************************************
* 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

@ -24,10 +24,10 @@
* SOFTWARE.
*****************************************************************************/
#ifdef STM32F2
#ifdef STM32F4
/**
* @file dmaF2.c
* @file dmaF4.c
* @brief Direct Memory Access peripheral support
*/
@ -117,33 +117,16 @@ void dma_detach_interrupt(dma_dev *dev, dma_stream stream) {
dev->handlers[stream].handler = NULL;
}
const uint8 dma_isr_bits_shift[] = { 0, 6, 16, 22};
uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream) {
if ( stream&0xFC ) return ((dev->regs->HISR)>>dma_isr_bits_shift[stream&0x03]) & 0x3d;
else return ((dev->regs->LISR)>>dma_isr_bits_shift[stream&0x03]) & 0x3d;
}
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;
}
if ( stream&0xFC ) dev->regs->HIFCR = (uint32)0x0000003d << dma_isr_bits_shift[stream&0x03];
else dev->regs->LIFCR = (uint32)0x0000003d << dma_isr_bits_shift[stream&0x03];
}
/*

View File

@ -25,7 +25,7 @@
*****************************************************************************/
/**
* @file dma.h
* @file dmaF4.h
*
* @author Marti Bolivar <mbolivar@leaflabs.com>;
* Original implementation by Michael Hope
@ -84,7 +84,7 @@ typedef struct dma_reg_map {
* Register bit definitions
*/
/* Channel configuration register */
/* Stream configuration register */
#define DMA_CR_CH0 (0x0 << 25)
#define DMA_CR_CH1 (0x1 << 25)
@ -136,6 +136,25 @@ typedef struct dma_reg_map {
#define DMA_CR_DMEIE (0x1 << 1)
#define DMA_CR_EN (0x1)
typedef enum dma_channel {
DMA_CH0 = DMA_CR_CH0, /**< Channel 0 */
DMA_CH1 = DMA_CR_CH1, /**< Channel 1 */
DMA_CH2 = DMA_CR_CH2, /**< Channel 2 */
DMA_CH3 = DMA_CR_CH3, /**< Channel 3 */
DMA_CH4 = DMA_CR_CH4, /**< Channel 4 */
DMA_CH5 = DMA_CR_CH5, /**< Channel 5 */
DMA_CH6 = DMA_CR_CH6, /**< Channel 6 */
DMA_CH7 = DMA_CR_CH7, /**< Channel 7 */
} dma_channel;
/* Device interrupt status register flags */
#define DMA_ISR_TCIF (1 << 5)
#define DMA_ISR_HTIF (1 << 4)
#define DMA_ISR_TEIF (1 << 3)
#define DMA_ISR_DMEIF (1 << 2)
#define DMA_ISR_FEIF (1 << 0)
/*
* Devices
*/
@ -166,25 +185,35 @@ extern dma_dev *DMA2;
* Convenience functions
*/
void dma_init(dma_dev *dev);
extern 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_MEM_BUF_0 = DMA_CR_CT0, /**< Current memory target buffer 0 */
DMA_MEM_BUF_1 = DMA_CR_CT1, /**< Current memory target buffer 1 */
DMA_DBL_BUF_MODE = DMA_CR_DBM, /**< Current memory double buffer mode */
DMA_PINC_OFFSET = DMA_CR_PINCOS, /**< Peripheral increment offset size */
DMA_MINC_MODE = DMA_CR_MINC, /**< Memory increment mode */
DMA_PINC_MODE = DMA_CR_PINC, /**< Peripheral increment mode */
DMA_CIRC_MODE = DMA_CR_CIRC, /**< Memory Circular mode */
DMA_FROM_PER = DMA_CR_DIR_P2M, /**< Read from memory to peripheral */
DMA_FROM_MEM = DMA_CR_DIR_M2P, /**< Read from memory to peripheral */
DMA_MEM_TO_MEM = DMA_CR_DIR_M2M, /**< Read from memory to memory */
DMA_PERIF_CTRL = DMA_CR_PFCTRL, /**< Peripheral flow controller */
DMA_PRIO_MEDIUM = DMA_CR_PL_MEDIUM, /**< Medium priority */
DMA_PRIO_HIGH = DMA_CR_PL_HIGH, /**< High priority */
DMA_PRIO_VERY_HIGH = DMA_CR_PL_VERY_HIGH, /**< Very high priority */
DMA_TRNS_CMPLT = DMA_CR_TCIE, /**< Interrupt on transfer completion */
DMA_TRNS_HALF = DMA_CR_HTIE, /**< Interrupt on half-transfer */
DMA_TRNS_ERR = DMA_CR_TEIE, /**< Interrupt on transfer error */
DMA_DIR_MODE_ERR = DMA_CR_DMEIE /**< Interrupt on direct mode error */
} 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_SIZE_8BITS = ( DMA_CR_MSIZE_8BITS|DMA_CR_PSIZE_8BITS ), /**< 8-bit transfers */
DMA_SIZE_16BITS = (DMA_CR_MSIZE_16BITS|DMA_CR_PSIZE_16BITS), /**< 16-bit transfers */
DMA_SIZE_32BITS = (DMA_CR_MSIZE_32BITS|DMA_CR_PSIZE_32BITS) /**< 32-bit transfers */
} dma_xfer_size;
/** DMA channel */
@ -201,17 +230,17 @@ typedef enum dma_stream {
static inline void dma_setup_transfer(dma_dev *dev,
dma_stream stream,
dma_channel channel,
dma_xfer_size trx_size,
__io void *peripheral_address,
__io void *memory_address0,
__io void *memory_address1,
uint32 flags,
uint32 fifo_flags) {
uint32 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
dev->regs->STREAM[stream].CR = ((flags|channel|trx_size) & 0x0feffffe); // mask out reserved and enable
}
static inline void dma_set_num_transfers(dma_dev *dev,
@ -220,6 +249,12 @@ static inline void dma_set_num_transfers(dma_dev *dev,
dev->regs->STREAM[stream].NDTR = num_transfers;
}
static inline void dma_set_fifo_flags(dma_dev *dev,
dma_stream stream,
uint8 fifo_flags) {
dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits
}
void dma_attach_interrupt(dma_dev *dev,
dma_stream stream,
void (*handler)(void));
@ -232,6 +267,7 @@ static inline void dma_enable(dma_dev *dev, dma_stream stream) {
static inline void dma_disable(dma_dev *dev, dma_stream stream) {
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
while (dev->regs->STREAM[stream].CR & DMA_CR_EN); // wait till EN bit is reset, see AN4031, chapter 4.1
}
/**

View File

@ -52,11 +52,7 @@ typedef struct exti_reg_map {
} 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 {

View File

@ -39,27 +39,28 @@
*/
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);
gpio_set_mode(PD0, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD1, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD8, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD9, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD10, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD14, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD15, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE7, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE8, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE9, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE10, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE11, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE12, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE13, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE14, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PE15, 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(PD11, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD12, GPIO_AF_OUTPUT_PP);
gpio_set_mode(PD13, GPIO_AF_OUTPUT_PP);
#if 0 // not available on LQFP package
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);
@ -76,18 +77,20 @@ void fsmc_sram_init_gpios(void) {
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);
#endif // not available on LQFP package
/* 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(PD4, GPIO_AF_OUTPUT_PP); // NOE
gpio_set_mode(PD5, GPIO_AF_OUTPUT_PP); // NWE
gpio_set_mode(GPIOD, 7, GPIO_AF_OUTPUT_PP); // NE1
gpio_set_mode(PD7, GPIO_AF_OUTPUT_PP); // NE1
#if 0 // not available on LQFP package
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
#endif // not available on LQFP package
gpio_set_mode(GPIOE, 0, GPIO_AF_OUTPUT_PP); // NBL0
gpio_set_mode(GPIOE, 1, GPIO_AF_OUTPUT_PP); // NBL1
gpio_set_mode(PE0, GPIO_AF_OUTPUT_PP); // NBL0
gpio_set_mode(PE1, GPIO_AF_OUTPUT_PP); // NBL1
}
#endif /* STM32_HIGH_DENSITY */

View File

@ -31,8 +31,102 @@
* (AFIO) prototypes, defines, and inlined access functions.
*/
#ifdef STM32F2
#include "gpioF2.h"
#else
#include "gpioF1.h"
#ifndef _GPIO_H_
#define _GPIO_H_
#include "libmaple.h"
#include "boards.h"
#ifdef __cplusplus
extern "C"{
#endif
/**
* @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(const 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_pin(uint8_t pin, uint8 val) {
if (val) {
(PIN_MAP[pin].gpio_device)->regs->BSRRL = BIT(pin&0x0F);
} else {
(PIN_MAP[pin].gpio_device)->regs->BSRRH = BIT(pin&0x0F);
}
}
static inline void gpio_set_pin(uint8_t pin) {
(PIN_MAP[pin].gpio_device)->regs->BSRRL = BIT(pin&0x0F);
}
static inline void gpio_clear_pin(uint8_t pin) {
(PIN_MAP[pin].gpio_device)->regs->BSRRH = BIT(pin&0x0F);
}
/**
* 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_pin(uint8_t pin) {
return (PIN_MAP[pin].gpio_device)->regs->IDR & BIT(pin&0x0F);
}
/**
* Toggle a pin configured as output push-pull.
* @param dev GPIO device.
* @param pin Pin on dev to toggle.
*/
static inline void gpio_toggle_pin(uint8_t pin) {
(PIN_MAP[pin].gpio_device)->regs->ODR = (PIN_MAP[pin].gpio_device)->regs->ODR ^ BIT(pin&0x0F);
}
/*
* GPIO Convenience routines
*/
extern void gpio_init(const gpio_dev *dev);
extern void gpio_init_all(void);
extern void gpio_set_mode(uint8_t pin, gpio_pin_mode mode);
extern void gpio_set_af_mode(uint8_t pin, int mode);
/*
* AFIO convenience routines
*/
extern void afio_init(void);
extern void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port);
extern void afio_remap(afio_remap_peripheral p);
/**
* @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

@ -1,200 +0,0 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
#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

@ -1,530 +0,0 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @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

@ -24,8 +24,6 @@
* SOFTWARE.
*****************************************************************************/
#ifdef STM32F2
/**
* @file gpio.c
* @brief GPIO initialization routine
@ -38,62 +36,57 @@
* GPIO devices
*/
gpio_dev gpioa = {
/** GPIO port A device. */
const 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 = {
/** GPIO port B device. */
const 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 = {
/** GPIO port C device. */
const 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 = {
/** GPIO port D device. */
const 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 = {
/** GPIO port E device. */
const 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 = {
#if 0 // not available on LQFP 100 package
/** GPIO port F device. */
const 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 = {
/** GPIO port G device. */
const 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
#endif
/*
@ -107,7 +100,7 @@ gpio_dev* const GPIOG = &gpiog;
*
* @param dev GPIO device to initialize.
*/
void gpio_init(gpio_dev *dev) {
void gpio_init(const gpio_dev *dev) {
rcc_clk_enable(dev->clk_id);
rcc_reset_dev(dev->clk_id);
}
@ -116,27 +109,29 @@ void gpio_init(gpio_dev *dev) {
* Initialize and reset all available GPIO devices.
*/
void gpio_init_all(void) {
gpio_init(GPIOA);
gpio_init(GPIOB);
gpio_init(GPIOC);
gpio_init(GPIOD);
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);
gpio_init(&GPIOE);
#if 0 // not available on LQFP 100 package
gpio_init(GPIOF);
gpio_init(GPIOG);
#endif // not available on LQFP 100 package
#endif
#ifdef ARDUINO_STM32F4_NETDUINO2PLUS
// PA8 Output the Master Clock MCO1
gpio_set_af_mode(GPIOA, 8, 0);
gpio_set_mode(GPIOA, 8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_af_mode(PA8, 0);
gpio_set_mode(PA8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
// PB4 as alternate MISO Input
gpio_set_af_mode(GPIOB, 4, 5);
gpio_set_af_mode(PB4, 5);
// PA5 as alternate SCK Output
gpio_set_af_mode(GPIOA, 5, 5);
gpio_set_af_mode(PA5, 5);
// PA7 as alternate MOSI Output
gpio_set_af_mode(GPIOA, 7, 5);
gpio_set_af_mode(PA7, 5);
#endif
}
@ -148,16 +143,17 @@ void gpio_init_all(void) {
* @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;
void gpio_set_mode(uint8_t io_pin, gpio_pin_mode mode) {
gpio_reg_map *regs = (PIN_MAP[io_pin].gpio_device)->regs;
uint8_t pin = io_pin&0x0f;
//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));
regs->MODER = (regs->MODER & ~( 3 << (pin<<1))) | (((mode >> 0) & 3) << (pin<<1));
regs->PUPDR = (regs->PUPDR & ~( 3 << (pin<<1))) | (((mode >> 2) & 3) << (pin<<1));
regs->OSPEEDR = (regs->OSPEEDR & ~( 3 << (pin<<1))) | (((mode >> 4) & 3) << (pin<<1));
regs->OTYPER = (regs->OTYPER & ~( 1 << (pin<<0))) | (((mode >> 6) & 1) << (pin<<0));
}
/**
@ -168,10 +164,11 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) {
* @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;
void gpio_set_af_mode(uint8_t io_pin, int mode) {
gpio_reg_map *regs = (PIN_MAP[io_pin].gpio_device)->regs;
uint8_t pin = io_pin&0x0F;
regs->AFR[pin/8] = (regs->AFR[pin/8] & ~(15 << (4*(pin&7)))) | (((mode >> 0) & 15) << (4*(pin&7)));
regs->AFR[pin>>3] = (regs->AFR[pin>>3] & ~(15 << ((pin&7)<<2))) | (((mode >> 0) & 15) << ((pin&7)<<2));
}
/*
@ -220,5 +217,3 @@ void afio_remap(afio_remap_peripheral remapping) {
}
}
#endif
#endif

View File

@ -31,8 +31,8 @@
* (AFIO) prototypes, defines, and inlined access functions.
*/
#ifndef _GPIO_H_
#define _GPIO_H_
#ifndef _GPIO_DEF_H_
#define _GPIO_DEF_H_
#include "libmaple.h"
#include "rcc.h"
@ -74,11 +74,14 @@ typedef enum afio_exti_port {
AFIO_EXTI_PD, /**< Use port D (PDx) pin. */
#ifdef STM32_HIGH_DENSITY
AFIO_EXTI_PE, /**< Use port E (PEx) pin. */
#if 0 // not available on LQFP 100 package
AFIO_EXTI_PF, /**< Use port F (PFx) pin. */
AFIO_EXTI_PG, /**< Use port G (PGx) pin. */
#endif // not available on LQFP 100 package
#endif
} afio_exti_port;
/** GPIO device type */
typedef struct gpio_dev {
gpio_reg_map *regs; /**< Register map */
@ -86,21 +89,18 @@ typedef struct gpio_dev {
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;
extern const gpio_dev GPIOA;
extern const gpio_dev GPIOB;
extern const gpio_dev GPIOC;
extern const gpio_dev GPIOD;
#ifdef STM32_HIGH_DENSITY
extern gpio_dev gpioe;
extern gpio_dev* const GPIOE;
extern const gpio_dev GPIOE;
#if 0 // not available on LQFP 100 package
extern gpio_dev gpiof;
extern gpio_dev* const GPIOF;
extern gpio_dev gpiog;
extern gpio_dev* const GPIOG;
#endif // not available on LQFP 100 package
#endif
/** GPIO port register map base pointer */
@ -110,8 +110,10 @@ extern gpio_dev* const GPIOG;
#define GPIOD_BASE ((struct gpio_reg_map*)0x40020C00)
#ifdef STM32_HIGH_DENSITY
#define GPIOE_BASE ((struct gpio_reg_map*)0x40021000)
#if 0 // not available on LQFP 100 package
#define GPIOF_BASE ((struct gpio_reg_map*)0x40021400)
#define GPIOG_BASE ((struct gpio_reg_map*)0x40021800)
#endif // not available on LQFP 100 package
#endif
/*
@ -190,61 +192,6 @@ typedef enum gpio_pin_mode {
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
@ -532,15 +479,6 @@ typedef enum afio_debug_cfg {
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
}

View File

@ -41,9 +41,9 @@
static i2c_dev i2c_dev1 = {
.regs = I2C1_BASE,
.gpio_port = &gpiob,
.sda_pin = 7,
.scl_pin = 6,
//.gpio_port = &gpiob,
.sda_pin = PB7,
.scl_pin = PB6,
.clk_id = RCC_I2C1,
.ev_nvic_line = NVIC_I2C1_EV,
.er_nvic_line = NVIC_I2C1_ER,
@ -54,9 +54,9 @@ i2c_dev* const I2C1 = &i2c_dev1;
static i2c_dev i2c_dev2 = {
.regs = I2C2_BASE,
.gpio_port = &gpiob,
.sda_pin = 11,
.scl_pin = 10,
//.gpio_port = &gpiob,
.sda_pin = PB11,
.scl_pin = PB10,
.clk_id = RCC_I2C2,
.ev_nvic_line = NVIC_I2C2_EV,
.er_nvic_line = NVIC_I2C2_ER,
@ -336,38 +336,38 @@ void __irq_i2c2_er(void) {
*/
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);
gpio_set_pin(dev->scl_pin);
gpio_set_pin(dev->sda_pin);
gpio_set_mode(dev->scl_pin, GPIO_OUTPUT_OD);
gpio_set_mode(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)) {
while (!gpio_read_pin(dev->sda_pin)) {
/* Wait for any clock stretching to finish */
while (!gpio_read_bit(dev->gpio_port, dev->scl_pin))
while (!gpio_read_pin(dev->scl_pin))
;
delay_us(10);
/* Pull low */
gpio_write_bit(dev->gpio_port, dev->scl_pin, 0);
gpio_clear_pin(dev->scl_pin);
delay_us(10);
/* Release high again */
gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
gpio_set_pin(dev->scl_pin);
delay_us(10);
}
/* Generate start then stop condition */
gpio_write_bit(dev->gpio_port, dev->sda_pin, 0);
gpio_clear_pin(dev->sda_pin);
delay_us(10);
gpio_write_bit(dev->gpio_port, dev->scl_pin, 0);
gpio_clear_pin(dev->scl_pin);
delay_us(10);
gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
gpio_set_pin(dev->scl_pin);
delay_us(10);
gpio_write_bit(dev->gpio_port, dev->sda_pin, 1);
gpio_set_pin(dev->sda_pin);
}
/**
@ -413,8 +413,8 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {
/* 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);
gpio_set_mode(dev->sda_pin, GPIO_AF_OUTPUT_OD);
gpio_set_mode(dev->scl_pin, GPIO_AF_OUTPUT_OD);
/* I2C1 and I2C2 are fed from APB1, clocked at 36MHz */
i2c_set_input_clk(dev, I2C_CLK);

View File

@ -78,7 +78,7 @@ typedef struct i2c_msg {
*/
typedef struct i2c_dev {
i2c_reg_map *regs; /**< Register map */
gpio_dev *gpio_port; /**< SDA, SCL pins' GPIO port */
//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 */

View File

@ -32,29 +32,31 @@
#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 */
// 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 USER_ADDR_RAM 0x20000C00
#define STACK_TOP 0x20000800
/*
#else
#define USER_ADDR_ROM 0x08005000
#define USER_ADDR_RAM 0x20000C00
#define STACK_TOP 0x20000800
#endif
*/
#endif

View File

@ -33,6 +33,8 @@
#ifndef _LIBMAPLE_TYPES_H_
#define _LIBMAPLE_TYPES_H_
#include <inttypes.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
@ -46,12 +48,15 @@ typedef long long int64;
typedef void (*voidFuncPtr)(void);
#define __io volatile
#define __attr_flash __attribute__((section (".USER_FLASH")))
#define __always_inline inline __attribute__((always_inline))
#define __IO volatile
#ifndef __attr_flash
#define __attr_flash __attribute__((section (".USER_FLASH")))
#endif
#ifndef __always_inline
#define __always_inline inline __attribute__((always_inline))
#endif
#ifndef NULL
#define NULL 0
#define NULL 0
#endif
#endif

View File

@ -29,8 +29,5 @@
* @brief reset and clock control definitions and prototypes
*/
#ifdef STM32F2
#include "rccF2.h"
#else
#include "rccF1.h"
#endif
#include "rccF4.h"

View File

@ -1,233 +0,0 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
#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

@ -1,572 +0,0 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @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

@ -24,7 +24,7 @@
* SOFTWARE.
*****************************************************************************/
#ifdef STM32F2
#ifdef STM32F4
/**
* @file rcc.c
@ -166,7 +166,6 @@ typedef struct
#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE)
#define RESET 0
typedef uint32 uint32_t;
void InitMCO1()
{
@ -175,8 +174,8 @@ void InitMCO1()
RCC->CFGR &= RCC_CFGR_MCO1_RESET_MASK;
RCC->CFGR |= RCC_CFGR_MCO1Source_HSE | RCC_CFGR_MCO1Div_1;
// PA8 Output the Master Clock MCO1
gpio_set_af_mode(GPIOA, 8, 0);
gpio_set_mode(GPIOA, 8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_af_mode(PA8, 0);
gpio_set_mode(PA8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
}

View File

@ -3,17 +3,11 @@ 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
@ -42,18 +36,6 @@ cSRCS_$(d) := adc.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 \
@ -69,11 +51,7 @@ else
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

View File

@ -83,25 +83,29 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
}
/**
* @brief Nonblocking SPI transmit.
* @brief Blocking 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;
void spi_tx(spi_dev *dev, void *buf, uint32 len)
{
spi_reg_map *regs = dev->regs;
if ( spi_dff(dev) == SPI_DFF_8_BIT ) {
uint8 * dp8 = (uint8*)buf;
while ( len-- ) {
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
regs->DR = *dp8++;
}
} else {
uint16 * dp16 = (uint16*)buf;
while ( len-- ) {
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
regs->DR = *dp16++;
}
}
}
/**
@ -157,8 +161,9 @@ void spi_rx_dma_disable(spi_dev *dev) {
*/
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);
#define MASK (SPI_CR1_CRCEN|SPI_CR1_DFF)
spi_irq_disable(dev, SPI_INTERRUPTS_ALL);
if ( (dev->regs->CR1&MASK)!=(cr1_config&MASK) ) spi_peripheral_disable(dev);
dev->regs->CR1 = cr1_config;
spi_peripheral_enable(dev);
}

View File

@ -213,31 +213,22 @@ typedef struct spi_dev {
void spi_init(spi_dev *dev);
struct gpio_dev;
/**
* @brief Configure GPIO bit modes for use as a SPI port's pins.
*
* @param dev SPI device
* @param as_master If true, configure as bus master; otherwise, as slave.
* @param nss_dev NSS pin's GPIO device
* @param nss_bit NSS pin's GPIO bit on nss_dev
* @param sck_dev SCK pin's GPIO device
* @param sck_bit SCK pin's GPIO bit on comm_dev
* @param miso_dev MISO pin's GPIO device
* @param miso_bit MISO pin's GPIO bit on comm_dev
* @param mosi_dev MOSI pin's GPIO device
* @param mosi_bit MOSI pin's GPIO bit on comm_dev
*/
extern void spi_config_gpios(spi_dev *dev,
uint8 as_master,
struct gpio_dev *nss_dev,
uint8 nss_bit,
struct gpio_dev *sck_dev,
uint8 sck_bit,
struct gpio_dev *miso_dev,
uint8 miso_bit,
struct gpio_dev *mosi_dev,
uint8 mosi_bit);
uint8 nss_pin,
uint8 sck_pin,
uint8 miso_pin,
uint8 mosi_pin);
/**
* @brief SPI mode configuration.
@ -312,7 +303,7 @@ 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_tx(spi_dev *dev, void *buf, uint32 len);
/**
* @brief Call a function on each SPI port

View File

@ -31,8 +31,8 @@
* @brief STM32F1 SPI/I2S series header.
*/
#ifndef _LIBMAPLE_STM32F1_SPI_H_
#define _LIBMAPLE_STM32F1_SPI_H_
#ifndef _LIBMAPLE_SPI_F4_H_
#define _LIBMAPLE_SPI_F4_H_
#include <libmaple/libmaple_types.h>
@ -62,17 +62,6 @@ extern struct spi_dev *SPI2;
extern struct spi_dev *SPI3;
#endif
/*
* Routines
*/
/* spi_gpio_cfg(): Backwards compatibility shim to spi_config_gpios() */
struct gpio_dev;
extern void spi_config_gpios(struct spi_dev*, uint8,
struct gpio_dev*, uint8,
struct gpio_dev*, uint8,
struct gpio_dev*, uint8,
struct gpio_dev*, uint8);
#ifdef __cplusplus
}

View File

@ -56,25 +56,21 @@ spi_dev *SPI3 = &spi3;
void spi_config_gpios(spi_dev *ignored,
uint8 as_master,
gpio_dev *nss_dev,
uint8 nss_bit,
gpio_dev *sck_dev,
uint8 sck_bit,
gpio_dev *miso_dev,
uint8 miso_bit,
gpio_dev *mosi_dev,
uint8 mosi_bit) {
uint8 nss_pin,
uint8 sck_pin,
uint8 miso_pin,
uint8 mosi_pin) {
if (as_master) {
// gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP);
gpio_set_mode(sck_dev, sck_bit, GPIO_AF_OUTPUT_PP);
gpio_set_mode(sck_pin, GPIO_AF_OUTPUT_PP);
// gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING);
gpio_set_mode(miso_dev, miso_bit, GPIO_AF_INPUT_PD);
gpio_set_mode(mosi_dev, mosi_bit, GPIO_AF_OUTPUT_PP);
gpio_set_mode(miso_pin, GPIO_AF_INPUT_PD);
gpio_set_mode(mosi_pin, GPIO_AF_OUTPUT_PP);
} else {
gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING);
gpio_set_mode(sck_dev, sck_bit, GPIO_INPUT_FLOATING);
gpio_set_mode(miso_dev, miso_bit, GPIO_AF_OUTPUT_PP);
gpio_set_mode(mosi_dev, mosi_bit, GPIO_INPUT_FLOATING);
gpio_set_mode(nss_pin, GPIO_INPUT_FLOATING);
gpio_set_mode(sck_pin, GPIO_INPUT_FLOATING);
gpio_set_mode(miso_pin, GPIO_AF_OUTPUT_PP);
gpio_set_mode(mosi_pin, GPIO_INPUT_FLOATING);
}
}

View File

@ -138,69 +138,8 @@
#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)
#if defined( STM32F4 )
#define STM32_TICKS_PER_US 168
#define STM32_NR_GPIO_PORTS 5
#define STM32_DELAY_US_MULT (STM32_TICKS_PER_US/3)

View File

@ -44,7 +44,7 @@
/* Update only. */
#define NR_BAS_HANDLERS 1
static timer_dev timer1 = {
timer_dev timer1 = {
.regs = { .adv = TIMER1_BASE },
.clk_id = RCC_TIMER1,
.type = TIMER_ADVANCED,
@ -53,7 +53,7 @@ static timer_dev timer1 = {
/** Timer 1 device (advanced) */
timer_dev *TIMER1 = &timer1;
static timer_dev timer2 = {
timer_dev timer2 = {
.regs = { .gen = TIMER2_BASE },
.clk_id = RCC_TIMER2,
.type = TIMER_GENERAL,
@ -62,7 +62,7 @@ static timer_dev timer2 = {
/** Timer 2 device (general-purpose) */
timer_dev *TIMER2 = &timer2;
static timer_dev timer3 = {
timer_dev timer3 = {
.regs = { .gen = TIMER3_BASE },
.clk_id = RCC_TIMER3,
.type = TIMER_GENERAL,
@ -71,7 +71,7 @@ static timer_dev timer3 = {
/** Timer 3 device (general-purpose) */
timer_dev *TIMER3 = &timer3;
static timer_dev timer4 = {
timer_dev timer4 = {
.regs = { .gen = TIMER4_BASE },
.clk_id = RCC_TIMER4,
.type = TIMER_GENERAL,
@ -81,7 +81,7 @@ static timer_dev timer4 = {
timer_dev *TIMER4 = &timer4;
#ifdef STM32_HIGH_DENSITY
static timer_dev timer5 = {
timer_dev timer5 = {
.regs = { .gen = TIMER5_BASE },
.clk_id = RCC_TIMER5,
.type = TIMER_GENERAL,
@ -90,7 +90,7 @@ static timer_dev timer5 = {
/** Timer 5 device (general-purpose) */
timer_dev *TIMER5 = &timer5;
static timer_dev timer6 = {
timer_dev timer6 = {
.regs = { .bas = TIMER6_BASE },
.clk_id = RCC_TIMER6,
.type = TIMER_BASIC,
@ -99,7 +99,7 @@ static timer_dev timer6 = {
/** Timer 6 device (basic) */
timer_dev *TIMER6 = &timer6;
static timer_dev timer7 = {
timer_dev timer7 = {
.regs = { .bas = TIMER7_BASE },
.clk_id = RCC_TIMER7,
.type = TIMER_BASIC,
@ -108,7 +108,7 @@ static timer_dev timer7 = {
/** Timer 7 device (basic) */
timer_dev *TIMER7 = &timer7;
static timer_dev timer8 = {
timer_dev timer8 = {
.regs = { .adv = TIMER8_BASE },
.clk_id = RCC_TIMER8,
.type = TIMER_ADVANCED,

View File

@ -113,13 +113,8 @@ typedef struct timer_bas_reg_map {
} timer_bas_reg_map;
#ifdef STM32F2
/** Timer 1 register map base pointer */
#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40010000)
#else
/** Timer 1 register map base pointer */
#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40012C00)
#endif
/** Timer 1 register map base pointer */
#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40010000)
/** Timer 2 register map base pointer */
#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000)
/** Timer 3 register map base pointer */
@ -133,14 +128,8 @@ typedef struct timer_bas_reg_map {
#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000)
/** Timer 7 register map base pointer */
#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400)
#ifdef STM32F2
/** Timer 8 register map base pointer */
#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40010400)
#else
/** Timer 8 register map base pointer */
#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40013400)
#endif
/** Timer 8 register map base pointer */
#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40010400)
#endif
/*

View File

@ -62,11 +62,7 @@ typedef struct usart_reg_map {
} 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
#define USART1_BASE ((struct usart_reg_map*)0x40011000)
/** USART2 register map base pointer */
#define USART2_BASE ((struct usart_reg_map*)0x40004400)
/** USART3 register map base pointer */

View File

@ -26,7 +26,7 @@
#include "usbd_ioreq.h"
#include "usbd_req.h"
#include "usbd_desc.h"
#include <VCP\usbd_desc.h>

View File

@ -24,7 +24,8 @@
#ifndef __USB_CDC_CORE_H_
#define __USB_CDC_CORE_H_
#include "usbd_ioreq.h"
#include <STM32_USB_Device_Library\Core\inc/usbd_ioreq.h>
#include <STM32_USB_OTG_Driver\inc\usb_core.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{

View File

@ -58,9 +58,10 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_core.h"
#include "usbd_desc.h"
#include "usbd_req.h"
#include <VCP\usb_conf.h>
#include <STM32_USB_Device_Library\Class\cdc\inc\usbd_cdc_core.h>
#include <VCP\usbd_desc.h>
#include <STM32_USB_Device_Library\Core\inc\usbd_req.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY

View File

@ -24,9 +24,9 @@
#define __USBD_CORE_H
/* Includes ------------------------------------------------------------------*/
#include "usb_dcd.h"
#include <STM32_USB_OTG_Driver/inc/usb_dcd.h>
#include "usbd_def.h"
#include "usbd_conf.h"
#include <VCP\usbd_conf.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{

View File

@ -24,7 +24,7 @@
#ifndef __USBD_DEF_H
#define __USBD_DEF_H
/* Includes ------------------------------------------------------------------*/
#include "usbd_conf.h"
#include <VCP\usbd_conf.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{

View File

@ -27,7 +27,7 @@
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
#include "usbd_core.h"
#include "usbd_conf.h"
#include <VCP\usbd_conf.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY

View File

@ -20,11 +20,11 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_req.h"
#include "usbd_ioreq.h"
#include "usb_dcd_int.h"
#include "usb_bsp.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_core.h>
#include <STM32_USB_Device_Library\Core\inc\usbd_req.h>
#include <STM32_USB_Device_Library\Core\inc\usbd_ioreq.h>
#include <STM32_USB_OTG_Driver\inc\usb_dcd_int.h>
#include <STM32_USB_OTG_Driver\inc\usb_bsp.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{

View File

@ -20,7 +20,7 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_ioreq.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/

View File

@ -20,9 +20,9 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_req.h"
#include "usbd_ioreq.h"
#include "usbd_desc.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_req.h>
#include <STM32_USB_Device_Library\Core\inc\usbd_ioreq.h>
#include <VCP\usbd_desc.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY

View File

@ -24,7 +24,7 @@
#define __USB_CORE_H__
/* Includes ------------------------------------------------------------------*/
#include "usb_conf.h"
#include <VCP\usbd_conf.h>
#include "usb_regs.h"
#include "usb_defines.h"

View File

@ -24,7 +24,7 @@
#define __USB_DEF_H__
/* Includes ------------------------------------------------------------------*/
#include "usb_conf.h"
#include <VCP\usbd_conf.h>
/** @addtogroup USB_OTG_DRIVER
* @{

View File

@ -23,6 +23,7 @@
#ifndef __USB_OTG__
#define __USB_OTG__
#include "usb_core.h"
/** @addtogroup USB_OTG_DRIVER
* @{

View File

@ -24,8 +24,8 @@
#define __USB_OTG_REGS_H__
/* Includes ------------------------------------------------------------------*/
#include "usb_conf.h"
#include <VCP\usbd_conf.h>
#include <libmaple\libmaple_types.h>
/** @addtogroup USB_OTG_DRIVER
* @{

View File

@ -20,8 +20,8 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_bsp.h"
#include "usb_core.h"
#include <STM32_USB_OTG_Driver\inc\usb_bsp.h>
#include <STM32_USB_OTG_Driver\inc\usb_core.h>
/** @addtogroup USB_OTG_DRIVER

View File

@ -20,8 +20,8 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_dcd.h"
#include "usb_bsp.h"
#include <STM32_USB_OTG_Driver\inc\usb_dcd.h>
#include <STM32_USB_OTG_Driver\inc\usb_bsp.h>
/** @addtogroup USB_OTG_DRIVER

View File

@ -20,12 +20,12 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_dcd_int.h"
#include <STM32_USB_OTG_Driver\inc\usb_dcd_int.h>
typedef int IRQn_Type;
#define __NVIC_PRIO_BITS 4
#define __Vendor_SysTickConfig 1
#include <core_cm4.h>
#include <VCP\core_cm4.h>
/** @addtogroup USB_OTG_DRIVER

View File

@ -141,7 +141,7 @@
#endif
#include <stdint.h> /*!< standard types definitions */
#include <core_cmInstr.h> /*!< Core Instruction Access */
#include "core_cmInstr.h" /*!< Core Instruction Access */
//#include <core_cmFunc.h> /*!< Core Function Access */
//#include <core_cm4_simd.h> /*!< Compiler specific SIMD Intrinsics */

View File

@ -80,7 +80,7 @@ typedef unsigned char u8;
typedef int IRQn_Type;
#define __NVIC_PRIO_BITS 4
#define __Vendor_SysTickConfig 1
#include <core_cm4.h>
#include "core_cm4.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver
* @{

View File

@ -21,13 +21,13 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_bsp.h"
#include <STM32_USB_OTG_Driver\inc\usb_bsp.h>
#include "usbd_conf.h"
#include <gpio.h>
#include <libmaple/gpio.h>
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
#define OTG_FS_IRQn 67
//typedef unsigned char uint8_t;
#include <misc.h>
#include "misc.h"
//#include "stm32f4_discovery.h"
@ -97,10 +97,10 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
{
// ala42
#define GPIO_AF_OTG1_FS ((uint8_t)0xA) /* OTG_FS Alternate Function mapping */
gpio_set_mode(GPIOA,11,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_mode(GPIOA,12,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_af_mode(GPIOA,11,GPIO_AF_OTG1_FS) ; // OTG_FS_DM
gpio_set_af_mode(GPIOA,12,GPIO_AF_OTG1_FS) ; // OTG_FS_DP
gpio_set_mode(BOARD_USB_DM_PIN,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_mode(BOARD_USB_DP_PIN,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_af_mode(BOARD_USB_DM_PIN,GPIO_AF_OTG1_FS) ; // OTG_FS_DM
gpio_set_af_mode(BOARD_USB_DP_PIN,GPIO_AF_OTG1_FS) ; // OTG_FS_DP
#ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED
gpio_set_mode(GPIOA, 8,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ);
gpio_set_af_mode(GPIOA, 8,GPIO_AF_OTG1_FS) ; // OTG_FS_SOF
@ -122,10 +122,10 @@ void USB_OTG_BSP_DeInit(USB_OTG_CORE_HANDLE *pdev)
{
// ala42
#define GPIO_AF0 ((uint8_t)0) /* OTG_FS Alternate Function mapping */
gpio_set_mode(GPIOA,11, GPIO_MODE_INPUT);
gpio_set_mode(GPIOA,12, GPIO_MODE_INPUT);
gpio_set_af_mode(GPIOA,11,GPIO_AF0) ; // OTG_FS_DM
gpio_set_af_mode(GPIOA,12,GPIO_AF0) ; // OTG_FS_DP
gpio_set_mode(BOARD_USB_DM_PIN, GPIO_MODE_INPUT);
gpio_set_mode(BOARD_USB_DP_PIN, GPIO_MODE_INPUT);
gpio_set_af_mode(BOARD_USB_DM_PIN,GPIO_AF0) ; // OTG_FS_DM
gpio_set_af_mode(BOARD_USB_DP_PIN,GPIO_AF0) ; // OTG_FS_DP
#ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED
gpio_set_mode(GPIOA, 8,GPIO_MODE_INPUT);
gpio_set_af_mode(GPIOA, 8,GPIO_AF0) ; // OTG_FS_SOF

View File

@ -173,7 +173,9 @@ typedef unsigned char u8;
#elif defined (__ICCARM__) /* IAR Compiler */
#define __packed __packed
#elif defined ( __GNUC__ ) /* GNU Compiler */
#ifndef __packed
#define __packed __attribute__ ((__packed__))
#endif
#elif defined (__TASKING__) /* TASKING Compiler */
#define __packed __unaligned
#endif /* __CC_ARM */
@ -206,7 +208,9 @@ typedef unsigned char u8;
#elif defined (__ICCARM__) /* IAR Compiler */
#define __packed __packed
#elif defined ( __GNUC__ ) /* GNU Compiler */
#ifndef __packed
#define __packed __attribute__ ((__packed__))
#endif
#elif defined (__TASKING__) /* TASKING Compiler */
#define __packed __unaligned
#endif /* __CC_ARM */

View File

@ -255,7 +255,7 @@ typedef struct {
void systemHardReset(void) {
SCB_TypeDef* rSCB = (SCB_TypeDef *) SCB_BASE;
typedef void (*funcPtr)(void);
//typedef void (*funcPtr)(void); // not used
/* Reset */
rSCB->AIRCR = (u32)AIRCR_RESET_REQ;

View File

@ -26,7 +26,7 @@
/* Includes ------------------------------------------------------------------*/
//#include "stm32f4xx.h"
#include "usbd_cdc_core.h"
#include <STM32_USB_Device_Library\Class\cdc\inc\usbd_cdc_core.h>
#include "usbd_conf.h"

View File

@ -25,6 +25,7 @@
/* Includes ------------------------------------------------------------------*/
//#include "stm32f4_discovery.h"
#include "usb_conf.h"
/** @defgroup USB_CONF_Exported_Defines
* @{

View File

@ -20,11 +20,11 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_core.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_core.h>
#include "usbd_desc.h"
#include "usbd_req.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_req.h>
#include "usbd_conf.h"
#include "usb_regs.h"
#include <STM32_USB_OTG_Driver\inc\usb_regs.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{

View File

@ -25,7 +25,7 @@
#define __USB_DESC_H
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_def.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{

View File

@ -20,8 +20,8 @@
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_usr.h"
#include "usbd_ioreq.h"
#include <STM32_USB_Device_Library\Core\inc\usbd_usr.h>
#include <STM32_USB_Device_Library\Core\inc\usbd_ioreq.h>
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY

View File

@ -1,27 +1,30 @@
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usbd_desc.h"
#ifndef _USBF4_USB_H_
#define _USBF4_USB_H_
#include <STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h>
#include <STM32_USB_Device_Library/Core/inc/usbd_usr.h>
#include <VCP\usbd_desc.h>
#include "usb.h"
#include <gpio.h>
#include <rccF2.h>
#include <usbd_cdc_vcp.h>
#include <libmaple/gpio.h>
#include <libmaple/rccF4.h>
#include <VCP\usbd_cdc_vcp.h>
#include <boards.h>
USB_OTG_CORE_HANDLE USB_OTG_dev;
void setupUSB (void) {
#define USB_DISC_DEV GPIOD
#define USB_DISC_PIN 11
gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_OD); // ala42
void setupUSB (void)
{
gpio_set_mode(BOARD_USB_DP_PIN, GPIO_OUTPUT_OD); // ala42
#ifdef USB_DISC_OD
//gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_OD); // ala42
#else
//gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_PP); // ala42 for active pull-up on disconnect pin
#endif
gpio_write_bit(USB_DISC_DEV, USB_DISC_PIN,0); // ala42
gpio_clear_pin(BOARD_USB_DP_PIN); // ala42
delay_us(200000);
/* setup the apb1 clock for USB */
@ -29,7 +32,7 @@ void setupUSB (void) {
//pRCC->APB1ENR |= RCC_APB1ENR_USBEN;
/* initialize the usb application */
gpio_write_bit(USB_DISC_DEV, USB_DISC_PIN, 1); // ala42 // presents us to the host
gpio_set_pin(BOARD_USB_DP_PIN); // ala42 // presents us to the host
USBD_Init(&USB_OTG_dev,
USB_OTG_FS_CORE_ID,
&USR_desc,
@ -93,7 +96,7 @@ RESULT usbPowerOff(void) {
void usbDsbISR(void) {};
#include "usb_dcd_int.h"
#include <STM32_USB_OTG_Driver\inc\usb_dcd_int.h>
void __irq_OTG_FS_IRQHandler(void)
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
@ -102,3 +105,5 @@ void __irq_OTG_FS_IRQHandler(void)
void x__irq_usbwakeup(void)
{
}
#endif

View File

@ -5,7 +5,7 @@
extern "C" {
#endif
#include "usb_conf.h"
#include <VCP\usb_conf.h>
typedef enum _RESULT
{

View File

@ -128,7 +128,7 @@ void throb(void) {
uint32 TOP_CNT = 0x0800;
uint32 i = 0;
gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_OUTPUT_PP);
gpio_set_mode(ERROR_LED_PIN, GPIO_OUTPUT_PP);
/* Error fade. */
while (1) {
if (CC == TOP_CNT) {
@ -143,9 +143,9 @@ void throb(void) {
}
if (i < CC) {
gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 1);
gpio_set_pin(ERROR_LED_PIN);
} else {
gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 0);
gpio_clear_pin(ERROR_LED_PIN);
}
i++;
}

View File

@ -29,11 +29,12 @@
* @brief Miscellaneous utility macros and procedures.
*/
#include "libmaple_types.h"
#ifndef _UTIL_H_
#define _UTIL_H_
#include "libmaple_types.h"
#include "delay.h"
#ifdef __cplusplus
extern "C"{
#endif

View File

@ -28,8 +28,8 @@
* @brief Arduino-style PWM implementation.
*/
#include "libmaple_types.h"
#include "timer.h"
#include <libmaple/libmaple_types.h>
#include <libmaple/timer.h>
#include "boards.h"
#include "pwm.h"

View File

@ -33,6 +33,8 @@
#include "wirish.h"
#include "usb.h"
#ifdef SERIAL_USB
#define USB_TIMEOUT 50
USBSerial::USBSerial(void) {
@ -132,7 +134,7 @@ uint8 USBSerial::pending(void) {
return usbGetPending();
}
uint8 USBSerial::isConnected(void) {
USBSerial::operator bool() {
return usbIsConnected() && usbIsConfigured();
}
@ -153,3 +155,5 @@ void USBSerial::disableBlockingTx(void) {
}
USBSerial SerialUSB;
#endif

View File

@ -33,6 +33,8 @@
#include "Stream.h"
#ifdef SERIAL_USB
/**
* @brief Virtual serial terminal.
*/
@ -57,7 +59,8 @@ public:
uint8 getRTS();
uint8 getDTR();
uint8 isConnected();
operator bool();
uint8 isConnected() { return (bool) *this; }
uint8 pending();
void enableBlockingTx(void);
@ -65,6 +68,14 @@ public:
};
extern USBSerial SerialUSB;
#define Serial SerialUSB
#endif
#else // _USB_SERIAL_H_
#define Serial Serial1
#endif // SERIAL_USB
#endif // _USB_SERIAL_H_

View File

@ -34,9 +34,9 @@
#define _WIRISH_H_
#include <stdlib.h>
#include "libmaple.h"
#include <stdio.h>
#include <stdint.h>
#include "wirish_types.h"
#include "boards.h"
#include "io.h"
#include "bits.h"
@ -44,10 +44,8 @@
#include "ext_interrupts.h"
#include "wirish_debug.h"
#include "wirish_math.h"
#include "wirish_time.h"
#include <wirish_constants.h>
#include "HardwareSPI.h"
#include "HardwareSerial.h"
#include <libmaple/HardwareSerial.h>
#include "HardwareTimer.h"
#include "usb_serial.h"
@ -55,9 +53,10 @@
#define HIGH 0x1
#define LOW 0x0
#define true 0x1
#define false 0x0
#ifndef true
#define true 0x1
#define false 0x0
#endif
#define lowByte(w) ((w) & 0xFF)
#define highByte(w) (((w) >> 8) & 0xFF)

View File

@ -28,9 +28,7 @@
* @brief Arduino-compatible ADC implementation.
*/
#include "libmaple.h"
#include "wirish.h"
#include "io.h"
/* Assumes that the ADC has been initialized and that the pin is set
* to INPUT_ANALOG */

View File

@ -1,5 +1,5 @@
#ifndef _WIRING_CONSTANTS_
#define _WIRING_CONSTANTS_
#ifndef _WIRISH_CONSTANTS_H_
#define _WIRISH_CONSTANTS_H_
#ifdef __cplusplus
extern "C"{

View File

@ -24,6 +24,9 @@
* SOFTWARE.
*****************************************************************************/
#ifndef _WIRISH_DEBUG_H_
#define _WIRISH_DEBUG_H_
/**
* @file wirish_debug.h
* @brief High level debug port configuration
@ -50,5 +53,7 @@ static inline void disableDebugPorts(void) {
* @see disableDebugPorts()
*/
static inline void enableDebugPorts(void) {
afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ);
afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY); //AFIO_DEBUG_FULL_SWJ);
}
#endif

View File

@ -29,7 +29,7 @@
*/
#include "wirish.h"
#include "io.h"
void pinMode(uint8 pin, WiringPinMode mode) {
gpio_pin_mode outputMode;
@ -72,7 +72,7 @@ void pinMode(uint8 pin, WiringPinMode mode) {
return;
}
gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode);
gpio_set_mode(pin, outputMode);
if (PIN_MAP[pin].timer_device != NULL) {
/* Enable/disable timer channels if we're switching into or
@ -84,48 +84,51 @@ void pinMode(uint8 pin, WiringPinMode mode) {
}
uint32 digitalRead(uint8 pin) {
uint32 digitalRead(uint8 pin)
{
if (pin >= BOARD_NR_GPIO_PINS) {
return 0;
}
return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ?
return gpio_read_pin(pin) ?
HIGH : LOW;
}
void digitalWrite(uint8 pin, uint8 val) {
void digitalWrite(uint8 pin, uint8 val)
{
if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);
gpio_write_pin(pin, val);
}
void togglePin(uint8 pin) {
void togglePin(uint8 pin)
{
if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit);
gpio_toggle_pin(pin);
}
#define BUTTON_DEBOUNCE_DELAY 1
uint8 isButtonPressed() {
if (digitalRead(BOARD_BUTTON_PIN)) {
uint8 isButtonPressed(uint8_t button) {
if (digitalRead(button)) {
delay(BUTTON_DEBOUNCE_DELAY);
while (digitalRead(BOARD_BUTTON_PIN))
while (digitalRead(button))
;
return true;
}
return false;
}
uint8 waitForButtonPress(uint32 timeout) {
uint8 waitForButtonPress(uint8_t button, uint32 timeout) {
uint32 start = millis();
uint32 time;
if (timeout == 0) {
while (!isButtonPressed())
while (!isButtonPressed(button))
;
return true;
}
@ -136,6 +139,6 @@ uint8 waitForButtonPress(uint32 timeout) {
time - start > timeout) {
return false;
}
} while (!isButtonPressed());
} while (!isButtonPressed(button));
return true;
}

View File

@ -29,8 +29,8 @@
* @brief Includes <math.h>; provides Arduino-compatible math routines.
*/
#ifndef _WIRING_MATH_H_
#define _WIRING_MATH_H_
#ifndef _WIRISH_MATH_H_
#define _WIRISH_MATH_H_
#include <math.h>

View File

@ -28,10 +28,10 @@
* @brief Delay implementation.
*/
#include "libmaple.h"
#include "systick.h"
#include <libmaple/libmaple.h>
#include <libmaple/systick.h>
#include "wirish_time.h"
#include "delay.h"
#include <libmaple/delay.h>
void delay(unsigned long ms) {
uint32 i;

View File

@ -32,10 +32,9 @@
#ifndef __WIRISH_TIME_H_
#define __WIRISH_TIME_H_
#include "libmaple.h"
#include "nvic.h"
#include "systick.h"
#include "boards.h"
#include <libmaple/nvic.h>
#include <libmaple/systick.h>
#define US_PER_MS 1000

View File

@ -30,14 +30,13 @@
* @brief Wirish library type definitions.
*/
#include "libmaple_types.h"
#include "gpio.h"
#include "timer.h"
#include "adc.h"
#ifndef _WIRISH_TYPES_H_
#define _WIRISH_TYPES_H_
#include <libmaple/gpio_def.h>
#include <libmaple/timer.h>
#include <libmaple/adc.h>
/**
* Invalid stm32_pin_info adc_channel value.
* @see stm32_pin_info
@ -48,16 +47,28 @@
* @brief Stores STM32-specific information related to a given Maple pin.
* @see PIN_MAP
*/
#ifdef BOARD_generic_f407v
// restructure members to build consecutive pairs
typedef struct stm32_pin_info {
gpio_dev *gpio_device; /**< Maple pin's GPIO device */
timer_dev *timer_device; /**< Pin's timer device, if any. */
const adc_dev *adc_device; /**< ADC device, if any. */
uint8 gpio_bit; /**< Pin's GPIO port bit. */
const gpio_dev * gpio_device; /**< Maple pin's GPIO device */
timer_dev * timer_device; /**< Pin's timer device, if any. */
uint8 timer_channel; /**< Timer channel, or 0 if none. */
uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */
uint8 filler;
const adc_dev *adc_device; /**< ADC device, if any. */
} stm32_pin_info;
#else
typedef struct stm32_pin_info {
const gpio_dev *gpio_device; /**< Maple pin's GPIO device */
timer_dev *timer_device; /**< Pin's timer device, if any. */
const adc_dev *adc_device; /**< ADC device, if any. */
uint8 timer_channel; /**< Timer channel, or 0 if none. */
uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */
} stm32_pin_info;
#endif
/**
* Variable attribute, instructs the linker to place the marked
* variable in Flash instead of RAM. */

View File

@ -7,3 +7,4 @@ paragraph=SPI for STM32F4
category=Communication
url=
architectures=STM32F4
maintainer=

View File

@ -40,9 +40,9 @@
#include "wirish.h"
#include "boards.h"
//#include "HardwareSerial.h"
#define DMA_TIMEOUT 100
#if CYCLES_PER_MICROSECOND != 72
#if CYCLES_PER_MICROSECOND != 168
/* TODO [0.2.0?] something smarter than this */
#warning "Unexpected clock speed; SPI frequency calculation will be incorrect"
#endif
@ -91,77 +91,115 @@ static const spi_pins board_spi_pins[] __FLASH__ = {
*/
SPIClass::SPIClass(uint32 spi_num) {
_currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed
switch (spi_num) {
#if BOARD_NR_SPI >= 1
case 1:
this->spi_d = SPI1;
_currentSetting->spi_d = SPI1;
break;
#endif
#if BOARD_NR_SPI >= 2
case 2:
this->spi_d = SPI2;
_currentSetting->spi_d = SPI2;
break;
#endif
#if BOARD_NR_SPI >= 3
case 3:
this->spi_d = SPI3;
_currentSetting->spi_d = SPI3;
break;
#endif
default:
ASSERT(0);
}
//pinMode(BOARD_SPI_DEFAULT_SS,OUTPUT);
clockDivider = SPI_BAUD_PCLK_DIV_16;
dataMode = SPI_MODE0;
// Init things specific to each SPI device
// clock divider setup is a bit of hack, and needs to be improved at a later date.
/*****************************************************************************/
// DMA / Channel / Stream
// Rx Tx
// SPI1: 2 / 3 / 0 (2) - 2 / 3 / 3 (5)
// SPI2: 1 / 0 / 3 - 1 / 0 / 4
// SPI3: 1 / 0 / 0 (2) - 1 / 0 / 5 (7)
/*****************************************************************************/
_settings[0].spi_d = SPI1;
_settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
#ifdef SPI_DMA
_settings[0].spiDmaDev = DMA2;
_settings[0].spiDmaChannel = DMA_CH3;
_settings[0].spiRxDmaStream = DMA_STREAM0; // alternative: DMA_STREAM2
_settings[0].spiTxDmaStream = DMA_STREAM3; // alternative: DMA_STREAM5
#endif
_settings[1].spi_d = SPI2;
_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
#ifdef SPI_DMA
_settings[1].spiDmaDev = DMA1;
_settings[1].spiDmaChannel = DMA_CH0;
_settings[1].spiRxDmaStream = DMA_STREAM3; // alternative: -
_settings[1].spiTxDmaStream = DMA_STREAM4; // alternative: -
#endif
#if BOARD_NR_SPI >= 3
_settings[2].spi_d = SPI3;
_settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock);
#ifdef SPI_DMA
_settings[2].spiDmaDev = DMA1;
_settings[2].spiDmaChannel = DMA_CH0;
_settings[2].spiRxDmaStream = DMA_STREAM0; // alternative: DMA_STREAM2
_settings[2].spiTxDmaStream = DMA_STREAM5; // alternative: DMA_STREAM7
#endif
#endif
}
/*
* Set up/tear down
*/
void SPIClass::updateSettings(void) {
uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE | SPI_SOFT_SS);
#ifdef SPI_DEBUG
Serial.print("spi_master_enable("); Serial.print(_currentSetting->clockDivider); Serial.print(","); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")");
#endif
spi_master_enable(_currentSetting->spi_d, (spi_baud_rate)_currentSetting->clockDivider, (spi_mode)_currentSetting->dataMode, flags);
}
void SPIClass::begin(void) {
uint32 flags = ((bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | SPI_DFF_8_BIT | SPI_SW_SLAVE | SPI_SOFT_SS);
spi_init(spi_d);
configure_gpios(spi_d, 1);
#ifdef SPI_DEBUG
Serial.print("spi_master_enable("); Serial.print(clockDivider); Serial.print(","); Serial.print(dataMode); Serial.print(","); Serial.print(flags); Serial.println(")");
#endif
spi_master_enable(spi_d, (spi_baud_rate)clockDivider, (spi_mode)dataMode, flags);
spi_init(_currentSetting->spi_d);
configure_gpios(_currentSetting->spi_d, 1);
updateSettings();
#ifdef SPI_USE_DMA_BUFFER
dmaSendBufferInit();
#endif
//Serial.println("SPI class begin - end");
}
void SPIClass::beginSlave(void) {
if (dataMode >= 4) {
ASSERT(0);
return;
}
uint32 flags = ((bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | SPI_DFF_8_BIT | SPI_SW_SLAVE);
spi_init(spi_d);
configure_gpios(spi_d, 0);
spi_init(_currentSetting->spi_d);
configure_gpios(_currentSetting->spi_d, 0);
uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_RX_ONLY);
#ifdef SPI_DEBUG
Serial.print("spi_slave_enable("); Serial.print(dataMode); Serial.print(","); Serial.print(flags); Serial.println(")");
Serial.print("spi_slave_enable("); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")");
#endif
spi_slave_enable(spi_d, (spi_mode)dataMode, flags);
spi_slave_enable(_currentSetting->spi_d, (spi_mode)_currentSetting->dataMode, flags);
}
void SPIClass::end(void) {
if (!spi_is_enabled(this->spi_d)) {
if (!spi_is_enabled(_currentSetting->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)) {
while (spi_is_rx_nonempty(_currentSetting->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);
volatile uint16 rx __attribute__((unused)) = spi_rx_reg(_currentSetting->spi_d);
}
while (!spi_is_tx_empty(this->spi_d))
while (!spi_is_tx_empty(_currentSetting->spi_d))
;
while (spi_is_busy(this->spi_d))
while (spi_is_busy(_currentSetting->spi_d))
;
spi_peripheral_disable(this->spi_d);
spi_peripheral_disable(_currentSetting->spi_d);
}
/* Roger Clark added 3 functions */
@ -170,8 +208,9 @@ void SPIClass::setClockDivider(uint32_t clockDivider)
#ifdef SPI_DEBUG
Serial.print("Clock divider set to "); Serial.println(clockDivider);
#endif
this->clockDivider = clockDivider;
this->begin();
_currentSetting->clockDivider = clockDivider;
uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_BR);
_currentSetting->spi_d->regs->CR1 = cr1 | (clockDivider & SPI_CR1_BR);
}
void SPIClass::setBitOrder(BitOrder bitOrder)
@ -179,8 +218,10 @@ void SPIClass::setBitOrder(BitOrder bitOrder)
#ifdef SPI_DEBUG
Serial.print("Bit order set to "); Serial.println(bitOrder);
#endif
this->bitOrder = bitOrder;
this->begin();
_currentSetting->bitOrder = bitOrder;
uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_LSBFIRST);
if ( bitOrder==LSBFIRST ) cr1 |= SPI_CR1_LSBFIRST;
_currentSetting->spi_d->regs->CR1 = cr1;
}
/* Victor Perez. Added to test changing datasize from 8 to 16 bit modes on the fly.
@ -189,11 +230,11 @@ void SPIClass::setBitOrder(BitOrder bitOrder)
*/
void SPIClass::setDataSize(uint32 datasize)
{
uint32 cr1 = this->spi_d->regs->CR1;
datasize &= SPI_CR1_DFF;
cr1 &= ~(SPI_CR1_DFF);
cr1 |= datasize;
this->spi_d->regs->CR1 = cr1;
_currentSetting->dataSize = datasize;
uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF);
uint8 en = spi_is_enabled(_currentSetting->spi_d);
spi_peripheral_disable(_currentSetting->spi_d);
_currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF) | en;
}
void SPIClass::setDataMode(uint8_t dataMode)
@ -212,13 +253,11 @@ SPI Mode CPOL CPHA Shift SCK-edge Capture SCK-edge
On the STM32 it appears to be
bit 1 - CPOL : Clock polarity
(This bit should not be changed when communication is ongoing)
0 : CLK to 0 when idle
1 : CLK to 1 when idle
bit 0 - CPHA : Clock phase
(This bit should not be changed when communication is ongoing)
0 : The first clock transition is the first data capture edge
1 : The second clock transition is the first data capture edge
@ -228,44 +267,32 @@ If someone finds this is not the case or sees a logic error with this let me kno
#ifdef SPI_DEBUG
Serial.print("Data mode set to "); Serial.println(dataMode);
#endif
this->dataMode = dataMode;
this->begin();
}
_currentSetting->dataMode = dataMode;
uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_CPOL|SPI_CR1_CPHA);
_currentSetting->spi_d->regs->CR1 = cr1 | (dataMode & (SPI_CR1_CPOL|SPI_CR1_CPHA));
}
void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
{
#ifdef SPI_DEBUG
Serial.println("SPIClass::beginTransaction");
#endif
//_SSPin=pin;
//pinMode(_SSPin,OUTPUT);
//digitalWrite(_SSPin,LOW);
setBitOrder(settings.bitOrder);
setDataMode(settings.dataMode);
setClockDivider(determine_baud_rate(spi_d, settings.clock));
setDataSize(settings.dataSize);
setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock));
begin();
#if 0
// code from SAM core
uint8_t mode = interruptMode;
if (mode > 0) {
if (mode < 16) {
if (mode & 1) PIOA->PIO_IDR = interruptMask[0];
if (mode & 2) PIOB->PIO_IDR = interruptMask[1];
if (mode & 4) PIOC->PIO_IDR = interruptMask[2];
if (mode & 8) PIOD->PIO_IDR = interruptMask[3];
} else {
interruptSave = interruptsStatus();
noInterrupts();
}
}
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(pin);
bitOrder[ch] = settings.border;
SPI_ConfigureNPCS(spi, ch, settings.config);
//setBitOrder(pin, settings.border);
//setDataMode(pin, settings.datamode);
//setClockDivider(pin, settings.clockdiv);
#endif
}
void SPIClass::beginTransactionSlave(SPISettings settings)
{
#ifdef SPI_DEBUG
Serial.println(F("SPIClass::beginTransactionSlave"));
#endif
setBitOrder(settings.bitOrder);
setDataMode(settings.dataMode);
setDataSize(settings.dataSize);
beginSlave();
}
void SPIClass::endTransaction(void)
@ -295,131 +322,154 @@ void SPIClass::endTransaction(void)
* I/O
*/
uint8 SPIClass::read(void) {
uint8 buf[1];
this->read(buf, 1);
return buf[0];
uint16 SPIClass::read(void)
{
while ( spi_is_rx_nonempty(_currentSetting->spi_d)==0 ) ;
return (uint16)spi_rx_reg(_currentSetting->spi_d);
}
void SPIClass::read(uint8 *buf, uint32 len) {
uint32 rxed = 0;
while (rxed < len) {
while (!spi_is_rx_nonempty(this->spi_d))
;
buf[rxed++] = (uint8)spi_rx_reg(this->spi_d);
}
void SPIClass::read(uint8 *buf, uint32 len)
{
if ( len == 0 ) return;
spi_rx_reg(_currentSetting->spi_d); // clear the RX buffer in case a byte is waiting on it.
spi_reg_map * regs = _currentSetting->spi_d->regs;
// start sequence: write byte 0
regs->DR = 0x00FF; // write the first byte
// main loop
while ( (--len) ) {
while( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag
noInterrupts(); // go atomic level - avoid interrupts to surely get the previously received data
regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag.
while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register
*buf++ = (uint8)(regs->DR); // read and store the received byte. This clears the RXNE flag.
interrupts(); // let systick do its job
}
// read remaining last byte
while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the Rx register
*buf++ = (uint8)(regs->DR); // read and store the received byte
}
void SPIClass::write(uint16 data) {
#ifdef SPI_DEBUG
// Serial.print("SPIClass::write("); Serial.print(data); Serial.println(")");
#endif
// this->write(&data, 1);
void SPIClass::write(uint16 data)
{
/* Added for 16bit data Victor Perez. Roger Clark
* Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte)
* The original method, of calling write(*data, length) .
* Improved speed by just directly writing the single byte to the SPI data reg and wait for completion,
* by taking the Tx code from transfer(byte)
* This almost doubles the speed of this function.
*/
spi_tx_reg(this->spi_d, data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
spi_tx_reg(_currentSetting->spi_d, data); // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
}
//void SPIClass::write(uint8 byte) {
// this->write(&byte, 1);
/* Roger Clark
* Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte)
* The original method, of calling write(*data, length) .
* This almost doubles the speed of this function.
*/
// spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
// while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
// while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
//}
void SPIClass::write(const uint8 *data, uint32 length) {
#ifdef SPI_DEBUG
Serial.print("SPIClass::write(data, "); Serial.print(length); Serial.println(")");
#endif
uint32 txed = 0;
while (txed < length) {
txed += spi_tx(this->spi_d, data + txed, length - txed);
}
while (spi_is_tx_empty(this->spi_d) == 0); // "4. After writing the last data item into the SPI_DR register, wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... then wait until BSY=0, this indicates that the transmission of the last data is complete."
void SPIClass::write(uint16 data, uint32 n)
{
// Added by stevstrong: Repeatedly send same data by the specified number of times
spi_reg_map * regs = _currentSetting->spi_d->regs;
while ( (n--)>0 ) {
regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty
}
while ( (regs->SR & SPI_SR_BSY) != 0); // wait until BSY=0 before returning
}
uint8 SPIClass::transfer(uint8 byte) const {
#ifdef SPI_DEBUG
// Serial.print("SPIClass::transfer("); Serial.print(byte); Serial.println(")");
#endif
uint8 b;
spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..."
b = spi_rx_reg(this->spi_d); // "... and read the last received data."
while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
return b;
void SPIClass::write(void *data, uint32 length)
{
spi_dev * spi_d = _currentSetting->spi_d;
spi_tx(spi_d, (void*)data, length); // data can be array of bytes or words
while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
}
uint8 SPIClass::transfer(uint8 byte) const
{
spi_dev * spi_d = _currentSetting->spi_d;
spi_rx_reg(spi_d); // read any previous data
spi_tx_reg(spi_d, byte); // Write the data item to be transmitted into the SPI_DR register
while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
return (uint8)spi_rx_reg(spi_d); // "... and read the last received data."
}
uint16_t SPIClass::transfer16(uint16_t wr_data) const
{
spi_dev * spi_d = _currentSetting->spi_d;
spi_rx_reg(spi_d); // read any previous data
spi_tx_reg(spi_d, wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
return (uint16)spi_rx_reg(spi_d); // "... and read the last received data."
}
#ifdef SPI_DMA
/* Roger Clark and Victor Perez, 2015
* Performs a DMA SPI transfer with at least a receive buffer.
* If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer.
* On exit TX buffer is not modified, and RX buffer cotains the received data.
* If a TX buffer is not provided, FF is sent over and over for the length of the transfer.
* On exit TX buffer is not modified, and RX buffer contains the received data.
* Still in progress.
*/
uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length) {
uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length)
{
if (length == 0) return 0;
uint8 b;
if (spi_is_rx_nonempty(this->spi_d) == 1) b = spi_rx_reg(this->spi_d); //Clear the RX buffer in case a byte is waiting on it.
dma1_ch3_Active=true;
dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
uint8 b = 0;
dma_init(_currentSetting->spiDmaDev);
// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
// RX
spi_rx_dma_enable(SPI1);
dma_setup_transfer(DMA1, DMA_CH2, &SPI1->regs->DR, DMA_SIZE_8BITS,
receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA
dma_set_num_transfers(DMA1, DMA_CH2, length);
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==SPI_DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
dma_setup_transfer( _currentSetting->spiDmaDev,
_currentSetting->spiRxDmaStream,
_currentSetting->spiDmaChannel,
dma_bit_size,
&_currentSetting->spi_d->regs->DR, // peripheral address
receiveBuf, // memory bank 0 address
NULL, // memory bank 1 address
(DMA_MINC_MODE | DMA_FROM_PER | DMA_PRIO_VERY_HIGH) // flags
);
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream, length);
dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream, 0);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);
// TX
spi_tx_dma_enable(SPI1);
if (!transmitBuf) {
static uint8_t ff = 0XFF;
transmitBuf = &ff;
dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS,
transmitBuf, DMA_SIZE_8BITS, (DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit FF repeatedly
uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM); // | DMA_TRNS_CMPLT);
if ( transmitBuf==0 ) {
static uint8_t ff = 0XFF;
transmitBuf = &ff;
flags &= ~((uint32)DMA_MINC_MODE); // remove increment mode
}
else {
dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS,
transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit buffer DMA
}
dma_set_num_transfers(DMA1, DMA_CH3, length);
dma_enable(DMA1, DMA_CH2);// enable receive
dma_enable(DMA1, DMA_CH3);// enable transmit
dma_setup_transfer( _currentSetting->spiDmaDev,
_currentSetting->spiTxDmaStream,
_currentSetting->spiDmaChannel,
dma_bit_size,
&_currentSetting->spi_d->regs->DR, // peripheral address
transmitBuf, // memory bank 0 address
NULL, // memory bank 1 address
flags
);
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, length);
dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, 0);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
// software enable sequence, see AN4031, chapter 4.3
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);// enable receive
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);// enable transmit
spi_rx_reg(_currentSetting->spi_d); //Clear the RX buffer in case a byte is waiting on it.
spi_rx_dma_enable(_currentSetting->spi_d);
spi_tx_dma_enable(_currentSetting->spi_d); // must be the last enable to avoid DMA error flag
// while (dma1_ch3_Active);
// if (receiveBuf) {
uint32_t m = millis();
while (dma1_ch3_Active) {
if ((millis() - m) > 100) {
dma1_ch3_Active = 0;
b = 2;
break;
}
while ((b = dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream) & DMA_ISR_TCIF)==0 ) {// wait for completion flag to be set
if ( b&(DMA_ISR_TEIF|DMA_ISR_DMEIF|DMA_ISR_FEIF) ) { b = 1; break; } // break on any error flag
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
if (b & DMA_ISR_TCIF) b = 0;
// }
while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
dma_disable(DMA1, DMA_CH3);
dma_disable(DMA1, DMA_CH2);
spi_rx_dma_disable(SPI1);
spi_tx_dma_disable(SPI1);
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
// software disable sequence, see AN4031, chapter 4.1
spi_tx_dma_disable(_currentSetting->spi_d);
spi_rx_dma_disable(_currentSetting->spi_d);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
return b;
}
@ -427,56 +477,45 @@ uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length
* Performs a DMA SPI send using a TX buffer.
* On exit TX buffer is not modified.
* Still in progress.
* 2016 - stevstrong - reworked to automatically detect bit size from SPI setting
*/
uint8 SPIClass::dmaSend(uint8 *transmitBuf, uint16 length, bool minc) {
uint8 SPIClass::dmaSend(void * transmitBuf, uint16 length, bool minc)
{
if (length == 0) return 0;
uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
uint8 b;
dma1_ch3_Active=true;
dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
uint8 b = 0;
dma_init(_currentSetting->spiDmaDev);
// TX
spi_tx_dma_enable(SPI1);
dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS,
transmitBuf, DMA_SIZE_8BITS, flags);// Transmit buffer DMA
dma_set_num_transfers(DMA1, DMA_CH3, length);
dma_enable(DMA1, DMA_CH3);// enable transmit
while (dma1_ch3_Active);
while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..."
b = spi_rx_reg(this->spi_d); // "... and read the last received data."
while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
dma_disable(DMA1, DMA_CH3);
spi_tx_dma_disable(SPI1);
return b;
}
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==SPI_DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
dma_setup_transfer( _currentSetting->spiDmaDev,
_currentSetting->spiTxDmaStream,
_currentSetting->spiDmaChannel,
dma_bit_size,
&_currentSetting->spi_d->regs->DR, // peripheral address
transmitBuf, // memory bank 0 address
NULL, // memory bank 1 address
( (DMA_MINC_MODE*minc) | DMA_FROM_MEM ) //| DMA_TRNS_CMPLT ) // flags
);// Transmit buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, length);
dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, 0);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);// enable transmit
spi_tx_dma_enable(_currentSetting->spi_d);
uint8 SPIClass::dmaSend(uint16 *transmitBuf, uint16 length, bool minc) {
if (length == 0) return 0;
uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
uint8 b;
dma1_ch3_Active=true;
dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
uint32_t m = millis();
while ((b = dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream) & DMA_ISR_TCIF)==0 ) {// wait for completion flag to be set
if ( b&(DMA_ISR_TEIF|DMA_ISR_DMEIF|DMA_ISR_FEIF) ) { b = 1; break; } // break on any error flag
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
if (b & DMA_ISR_TCIF) b = 0;
// TX
spi_tx_dma_enable(SPI1);
dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_16BITS,
transmitBuf, DMA_SIZE_16BITS, flags);// Transmit buffer DMA
dma_set_num_transfers(DMA1, DMA_CH3, length);
dma_enable(DMA1, DMA_CH3);// enable transmit
while (dma1_ch3_Active);
while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..."
b = spi_rx_reg(this->spi_d); // "... and read the last received data."
while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
dma_disable(DMA1, DMA_CH3);
spi_tx_dma_disable(SPI1);
return b;
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
spi_tx_dma_disable(_currentSetting->spi_d);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
return b;
}
#endif
void SPIClass::attachInterrupt(void) {
@ -492,19 +531,19 @@ void SPIClass::detachInterrupt(void) {
*/
uint8 SPIClass::misoPin(void) {
return dev_to_spi_pins(this->spi_d)->miso;
return dev_to_spi_pins(_currentSetting->spi_d)->miso;
}
uint8 SPIClass::mosiPin(void) {
return dev_to_spi_pins(this->spi_d)->mosi;
return dev_to_spi_pins(_currentSetting->spi_d)->mosi;
}
uint8 SPIClass::sckPin(void) {
return dev_to_spi_pins(this->spi_d)->sck;
return dev_to_spi_pins(_currentSetting->spi_d)->sck;
}
uint8 SPIClass::nssPin(void) {
return dev_to_spi_pins(this->spi_d)->nss;
return dev_to_spi_pins(_currentSetting->spi_d)->nss;
}
/*
@ -512,18 +551,13 @@ uint8 SPIClass::nssPin(void) {
*/
uint8 SPIClass::send(uint8 data) {
uint8 buf[] = {data};
return this->send(buf, 1);
this->write(data);
return 1;
}
uint8 SPIClass::send(uint8 *buf, uint32 len) {
uint32 txed = 0;
uint8 ret = 0;
while (txed < len) {
this->write(buf[txed++]);
ret = this->read();
}
return ret;
this->write(buf, len);
return len;
}
uint8 SPIClass::recv(void) {
@ -585,29 +619,26 @@ static void configure_gpios(spi_dev *dev, bool as_master) {
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(pins->nss, 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(pins->sck, 5);
gpio_set_af_mode(pins->miso, 5);
gpio_set_af_mode(pins->mosi, 5);
} else {
if(nssi) {
if(!as_master) {
gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 6);
gpio_set_af_mode(pins->nss, 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(pins->sck, 6);
gpio_set_af_mode(pins->miso, 6);
gpio_set_af_mode(pins->mosi, 6);
}
#endif
spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit,
scki->gpio_device, scki->gpio_bit,
misoi->gpio_device, misoi->gpio_bit,
mosii->gpio_device, mosii->gpio_bit);
spi_config_gpios(dev, as_master, pins->nss, pins->sck, pins->miso, pins->mosi);
}
static const spi_baud_rate baud_rates[8] __FLASH__ = {
@ -634,6 +665,8 @@ static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) {
{
case RCC_APB2: clock = STM32_PCLK2; break; // 72 Mhz
case RCC_APB1: clock = STM32_PCLK1; break; // 36 Mhz
case RCC_AHB1: break;
default: break;
}
clock /= 2;
i = 0;
@ -646,4 +679,3 @@ static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) {
//SPIClass SPI(3);

View File

@ -34,18 +34,16 @@
/* TODO [0.1.0] Remove deprecated methods. */
#ifndef _SPI_H_INCLUDED
#define _SPI_H_INCLUDED
#ifndef _LIB_SPI_H_
#define _LIB_SPI_H_
#include <libmaple/libmaple_types.h>
#include <libmaple/spi.h>
#include <libmaple/dma.h>
#include <boards.h>
#include <stdint.h>
#include <wirish.h>
#define SPI_DMA
// SPI_HAS_TRANSACTION means SPI has
// - beginTransaction()
// - endTransaction()
@ -96,34 +94,61 @@
#define SPI_MODE2 SPI_MODE_2
#define SPI_MODE3 SPI_MODE_3
#define SPI_DATA_SIZE_8BIT SPI_CR1_DFF_8_BIT
#define SPI_DATA_SIZE_16BIT SPI_CR1_DFF_16_BIT
class SPISettings {
public:
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode);
init_AlwaysInline(clock, bitOrder, dataMode, SPI_DATA_SIZE_8BIT);
} else {
init_MightInline(clock, bitOrder, dataMode);
init_MightInline(clock, bitOrder, dataMode, SPI_DATA_SIZE_8BIT);
}
}
SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); }
private:
void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
init_AlwaysInline(clock, bitOrder, dataMode);
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode, dataSize);
} else {
init_MightInline(clock, bitOrder, dataMode, dataSize);
}
}
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) {
SPISettings(uint32_t clock) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, MSBFIRST, SPI_MODE0, SPI_DATA_SIZE_8BIT);
} else {
init_MightInline(clock, MSBFIRST, SPI_MODE0, SPI_DATA_SIZE_8BIT);
}
}
SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, SPI_DATA_SIZE_8BIT); }
private:
void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) {
init_AlwaysInline(clock, bitOrder, dataMode, dataSize);
}
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) __attribute__((__always_inline__)) {
this->clock = clock;
this->bitOrder = bitOrder;
this->dataMode = dataMode;
this->dataSize = dataSize;
}
uint32_t clock;
BitOrder bitOrder;
uint8_t dataMode;
uint32_t dataSize;
spi_dev *spi_d;
uint32_t clockDivider;
#ifdef SPI_DMA
dma_dev* spiDmaDev;
dma_channel spiDmaChannel;
dma_stream spiRxDmaStream, spiTxDmaStream;
#endif
friend class SPIClass;
};
volatile static bool dma1_ch3_Active;
/**
* @brief Wirish SPI interface.
*
@ -133,18 +158,11 @@ volatile static bool dma1_ch3_Active;
class SPIClass {
public:
/**
* @param spiPortNumber Number of the SPI port to manage.
*/
SPIClass(uint32 spiPortNumber);
/*
* Set up/tear down
*/
/**
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
@ -175,6 +193,8 @@ public:
void beginTransaction(uint8_t pin, SPISettings settings);
void endTransaction(void);
void beginTransactionSlave(SPISettings settings);
void setClockDivider(uint32_t clockDivider);
void setBitOrder(BitOrder bitOrder);
void setDataMode(uint8_t dataMode);
@ -195,40 +215,40 @@ public:
*/
/**
* @brief Return the next unread byte.
* @brief Return the next unread byte/word.
*
* If there is no unread byte waiting, this function will block
* If there is no unread byte/word waiting, this function will block
* until one is received.
*/
uint8 read(void);
uint16 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
* @param length Number of bytes to store in buffer. This
* function will block until the desired number of
* bytes have been read.
*/
void read(uint8 *buffer, uint32 length);
/**
* @brief Transmit a byte.
* @param data Byte to transmit.
*/
// void write(uint8 data);
/**
* @brief Transmit a half word.
* @brief Transmit one byte/word.
* @param data to transmit.
*/
void write(uint16 data);
/**
* @brief Transmit multiple bytes.
* @param buffer Bytes to transmit.
* @param length Number of bytes in buffer to transmit.
* @brief Transmit one byte/word a specified number of times.
* @param data to transmit.
*/
void write(const uint8 *buffer, uint32 length);
void write(uint16 data, uint32 n);
/**
* @brief Transmit multiple bytes/words.
* @param buffer Bytes/words to transmit.
* @param length Number of bytes/words in buffer to transmit.
*/
void write(void * buffer, uint32 length);
/**
* @brief Transmit a byte, then return the next unread byte.
@ -239,9 +259,12 @@ public:
* @return Next unread byte.
*/
uint8 transfer(uint8 data) const;
uint16_t transfer16(uint16_t data) const;
#ifdef SPI_DMA
/**
* @brief Sets up a DMA Transfer for "length" bytes.
* The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting.
*
* This function transmits and receives to buffers.
*
@ -249,30 +272,19 @@ public:
* @param receiveBuf buffer Bytes to save received data.
* @param length Number of bytes in buffer to transmit.
*/
uint8 dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length);
uint8 dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length);
/**
* @brief Sets up a DMA Transmit for bytes.
* @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode.
* The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting.
*
* This function transmits and does not care about the RX fifo.
*
* @param transmitBuf buffer Bytes to transmit,
* @param length Number of bytes in buffer to transmit.
* @param minc Set to use Memory Increment mode, clear to use Circular mode.
*/
uint8 dmaSend(uint8 *transmitBuf, uint16 length, bool minc = 1);
/**
* @brief Sets up a DMA Transmit for half words.
* SPI PERFIPHERAL MUST BE SET TO 16 BIT MODE BEFORE
*
* This function transmits and does not care about the RX fifo.
* This function only transmits and does not care about the RX fifo.
*
* @param data buffer half words to transmit,
* @param length Number of bytes in buffer to transmit.
* @param minc Set to use Memory Increment mode (default if blank), clear to use Circular mode.
*/
uint8 dmaSend(uint16 *transmitBuf, uint16 length, bool minc = 1);
uint8 dmaSend(void * transmitBuf, uint16 length, bool minc = 1);
#endif
/*
* Pin accessors
@ -304,7 +316,24 @@ public:
* @brief Get a pointer to the underlying libmaple spi_dev for
* this HardwareSPI instance.
*/
spi_dev* c_dev(void) { return this->spi_d; }
spi_dev* c_dev(void) { return _currentSetting->spi_d; }
spi_dev *dev(){ return _currentSetting->spi_d;}
/**
* @brief Sets the number of the SPI peripheral to be used by
* this HardwareSPI instance.
*
* @param spi_num Number of the SPI port. 1-2 in low density devices
* or 1-3 in high density devices.
*/
void setModule(int spi_num)
{
_currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed
}
/* -- The following methods are deprecated --------------------------- */
@ -338,26 +367,13 @@ public:
*/
uint8 recv(void);
spi_dev *dev(){ return spi_d;}
private:
static inline void DMA1_CH3_Event() {
dma1_ch3_Active = 0;
// dma_disable(DMA1, DMA_CH3);
// dma_disable(DMA1, DMA_CH2);
// To Do. Need to wait for
}
spi_dev *spi_d;
uint8_t _SSPin;
uint32_t clockDivider;
uint8_t dataMode;
BitOrder bitOrder;
SPISettings _settings[BOARD_NR_SPI];
SPISettings *_currentSetting;
void updateSettings(void);
};
extern SPIClass SPI; // needed bx SdFat(EX) lib
extern SPIClass SPI;//(1);// dummy params
#endif

Some files were not shown because too many files have changed in this diff Show More