Add software

This commit is contained in:
RocketGod
2022-09-22 09:26:57 -07:00
parent fee0ab05fd
commit 957ea3d712
4511 changed files with 1943182 additions and 0 deletions

View File

@ -0,0 +1,557 @@
/** @defgroup can_file CAN
@ingroup STM32F_files
@brief <b>libopencm3 STM32Fxxx CAN</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010 Piotr Esden-Tempski <piotr@esden.net>
@date 12 November 2012
Devices can have up to two CAN peripherals. The peripherals support up to 1MBit
transmission rate. The peripheral has several filters for incoming messages that
can be distributed between two FIFOs and three transmit mailboxes.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/can.h>
#if defined(STM32F1)
# include <libopencm3/stm32/f1/rcc.h>
#elif defined(STM32F2)
# include <libopencm3/stm32/f2/rcc.h>
#elif defined(STM32F4)
# include <libopencm3/stm32/f4/rcc.h>
#else
# error "stm32 family not defined."
#endif
/* Timeout for CAN INIT acknowledge
* this value is difficult to define.
* INIT is set latest after finishing the current transfer.
* Assuming the lowest CAN speed of 100kbps one CAN frame may take about 1.6ms
* WAIT loop timeout varies on compiler switches, optimization, CPU architecture
* and CPU speed
*
* The same timeout value is used for leaving INIT where the longest time is
* 11 bits(110 us on 100 kbps).
*/
#define CAN_MSR_INAK_TIMEOUT 0x0000FFFF
/*---------------------------------------------------------------------------*/
/** @brief CAN Reset
The CAN peripheral and all its associated configuration registers are placed in
the reset condition. The reset is effective via the RCC peripheral reset
system.
@param[in] canport Unsigned int32. CAN block register address base @ref
can_reg_base.
*/
void can_reset(uint32_t canport)
{
if (canport == CAN1) {
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST);
} else {
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST);
}
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Init
Initialize the selected CAN peripheral block.
@param[in] canport Unsigend int32. CAN register base address @ref can_reg_base.
@param[in] ttcm bool. Time triggered communication mode.
@param[in] abom bool. Automatic bus-off management.
@param[in] awum bool. Automatic wakeup mode.
@param[in] nart bool. No automatic retransmission.
@param[in] rflm bool. Receive FIFO locked mode.
@param[in] txfp bool. Transmit FIFO priority.
@param[in] sjw Unsigned int32. Resynchronization time quanta jump width.
@param[in] ts1 Unsigned int32. Time segment 1 time quanta width.
@param[in] ts2 Unsigned int32. Time segment 2 time quanta width.
@param[in] brp Unsigned int32. Baud rate prescaler.
@returns int 0 on success, 1 on initialization failure.
*/
int can_init(uint32_t canport, bool ttcm, bool abom, bool awum, bool nart,
bool rflm, bool txfp, uint32_t sjw, uint32_t ts1, uint32_t ts2,
uint32_t brp, bool loopback, bool silent)
{
volatile uint32_t wait_ack;
int ret = 0;
/* Exit from sleep mode. */
CAN_MCR(canport) &= ~CAN_MCR_SLEEP;
/* Request initialization "enter". */
CAN_MCR(canport) |= CAN_MCR_INRQ;
/* Wait for acknowledge. */
wait_ack = CAN_MSR_INAK_TIMEOUT;
while ((--wait_ack) &&
((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK));
/* Check the acknowledge. */
if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK) {
return 1;
}
/* clear can timing bits */
CAN_BTR(canport) = 0;
/* Set the automatic bus-off management. */
if (ttcm) {
CAN_MCR(canport) |= CAN_MCR_TTCM;
} else {
CAN_MCR(canport) &= ~CAN_MCR_TTCM;
}
if (abom) {
CAN_MCR(canport) |= CAN_MCR_ABOM;
} else {
CAN_MCR(canport) &= ~CAN_MCR_ABOM;
}
if (awum) {
CAN_MCR(canport) |= CAN_MCR_AWUM;
} else {
CAN_MCR(canport) &= ~CAN_MCR_AWUM;
}
if (nart) {
CAN_MCR(canport) |= CAN_MCR_NART;
} else {
CAN_MCR(canport) &= ~CAN_MCR_NART;
}
if (rflm) {
CAN_MCR(canport) |= CAN_MCR_RFLM;
} else {
CAN_MCR(canport) &= ~CAN_MCR_RFLM;
}
if (txfp) {
CAN_MCR(canport) |= CAN_MCR_TXFP;
} else {
CAN_MCR(canport) &= ~CAN_MCR_TXFP;
}
if (silent) {
CAN_BTR(canport) |= CAN_BTR_SILM;
} else {
CAN_BTR(canport) &= ~CAN_BTR_SILM;
}
if (loopback) {
CAN_BTR(canport) |= CAN_BTR_LBKM;
} else {
CAN_BTR(canport) &= ~CAN_BTR_LBKM;
}
/* Set bit timings. */
CAN_BTR(canport) |= sjw | ts2 | ts1 |
((brp - 1ul) & CAN_BTR_BRP_MASK);
/* Request initialization "leave". */
CAN_MCR(canport) &= ~CAN_MCR_INRQ;
/* Wait for acknowledge. */
wait_ack = CAN_MSR_INAK_TIMEOUT;
while ((--wait_ack) &&
((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK));
if ((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK) {
ret = 1;
}
return ret;
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Filter Init
Initialize incoming message filter and assign to FIFO.
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] nr Unsigned int32. ID number of the filter.
@param[in] scale_32bit bool. 32-bit scale for the filter?
@param[in] id_list_mode bool. ID list filter mode?
@param[in] fr1 Unsigned int32. First filter register content.
@param[in] fr2 Unsigned int32. Second filter register content.
@param[in] fifo Unsigned int32. FIFO id.
@param[in] enable bool. Enable filter?
*/
void can_filter_init(uint32_t canport, uint32_t nr, bool scale_32bit,
bool id_list_mode, uint32_t fr1, uint32_t fr2,
uint32_t fifo, bool enable)
{
uint32_t filter_select_bit = 0x00000001 << nr;
/* Request initialization "enter". */
CAN_FMR(canport) |= CAN_FMR_FINIT;
/* Deactivate the filter. */
CAN_FA1R(canport) &= ~filter_select_bit;
if (scale_32bit) {
/* Set 32-bit scale for the filter. */
CAN_FS1R(canport) |= filter_select_bit;
} else {
/* Set 16-bit scale for the filter. */
CAN_FS1R(canport) &= ~filter_select_bit;
}
if (id_list_mode) {
/* Set filter mode to ID list mode. */
CAN_FM1R(canport) |= filter_select_bit;
} else {
/* Set filter mode to id/mask mode. */
CAN_FM1R(canport) &= ~filter_select_bit;
}
/* Set the first filter register. */
CAN_FiR1(canport, nr) = fr1;
/* Set the second filter register. */
CAN_FiR2(canport, nr) = fr2;
/* Select FIFO0 or FIFO1 as filter assignement. */
if (fifo) {
CAN_FFA1R(canport) |= filter_select_bit; /* FIFO1 */
} else {
CAN_FFA1R(canport) &= ~filter_select_bit; /* FIFO0 */
}
if (enable) {
CAN_FA1R(canport) |= filter_select_bit; /* Activate filter. */
}
/* Request initialization "leave". */
CAN_FMR(canport) &= ~CAN_FMR_FINIT;
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Initialize a 16bit Message ID Mask Filter
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] nr Unsigned int32. ID number of the filter.
@param[in] id1 Unsigned int16. First message ID to filter.
@param[in] mask1 Unsigned int16. First message ID bit mask.
@param[in] id2 Unsigned int16. Second message ID to filter.
@param[in] mask2 Unsigned int16. Second message ID bit mask.
@param[in] fifo Unsigned int32. FIFO id.
@param[in] enable bool. Enable filter?
*/
void can_filter_id_mask_16bit_init(uint32_t canport, uint32_t nr, uint16_t id1,
uint16_t mask1, uint16_t id2,
uint16_t mask2, uint32_t fifo, bool enable)
{
can_filter_init(canport, nr, false, false,
((uint32_t)id1 << 16) | (uint32_t)mask1,
((uint32_t)id2 << 16) | (uint32_t)mask2, fifo, enable);
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Initialize a 32bit Message ID Mask Filter
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] nr Unsigned int32. ID number of the filter.
@param[in] id Unsigned int32. Message ID to filter.
@param[in] mask Unsigned int32. Message ID bit mask.
@param[in] fifo Unsigned int32. FIFO id.
@param[in] enable bool. Enable filter?
*/
void can_filter_id_mask_32bit_init(uint32_t canport, uint32_t nr, uint32_t id,
uint32_t mask, uint32_t fifo, bool enable)
{
can_filter_init(canport, nr, true, false, id, mask, fifo, enable);
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Initialize a 16bit Message ID List Filter
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] nr Unsigned int32. ID number of the filter.
@param[in] id1 Unsigned int16. First message ID to match.
@param[in] id2 Unsigned int16. Second message ID to match.
@param[in] id3 Unsigned int16. Third message ID to match.
@param[in] id4 Unsigned int16. Fourth message ID to match.
@param[in] fifo Unsigned int32. FIFO id.
@param[in] enable bool. Enable filter?
*/
void can_filter_id_list_16bit_init(uint32_t canport, uint32_t nr,
uint16_t id1, uint16_t id2,
uint16_t id3, uint16_t id4,
uint32_t fifo, bool enable)
{
can_filter_init(canport, nr, false, true,
((uint32_t)id1 << 16) | (uint32_t)id2,
((uint32_t)id3 << 16) | (uint32_t)id4, fifo, enable);
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Initialize a 32bit Message ID List Filter
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] nr Unsigned int32. ID number of the filter.
@param[in] id1 Unsigned int32. First message ID to match.
@param[in] id2 Unsigned int32. Second message ID to match.
@param[in] fifo Unsigned int32. FIFO id.
@param[in] enable bool. Enable filter?
*/
void can_filter_id_list_32bit_init(uint32_t canport, uint32_t nr,
uint32_t id1, uint32_t id2,
uint32_t fifo, bool enable)
{
can_filter_init(canport, nr, true, true, id1, id2, fifo, enable);
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Enable IRQ
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] irq Unsigned int32. IRQ bit(s).
*/
void can_enable_irq(uint32_t canport, uint32_t irq)
{
CAN_IER(canport) |= irq;
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Disable IRQ
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] irq Unsigned int32. IRQ bit(s).
*/
void can_disable_irq(uint32_t canport, uint32_t irq)
{
CAN_IER(canport) &= ~irq;
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Transmit Message
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] id Unsigned int32. Message ID.
@param[in] ext bool. Extended message ID?
@param[in] rtr bool. Request transmit?
@param[in] length Unsigned int8. Message payload length.
@param[in] data Unsigned int8[]. Message payload data.
@returns int 0, 1 or 2 on success and depending on which outgoing mailbox got
selected. -1 if no mailbox was available and no transmission got queued.
*/
int can_transmit(uint32_t canport, uint32_t id, bool ext, bool rtr,
uint8_t length, uint8_t *data)
{
int ret = 0;
uint32_t mailbox = 0;
union {
uint8_t data8[4];
uint32_t data32;
} tdlxr, tdhxr;
/* Check which transmit mailbox is empty if any. */
if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
ret = 0;
mailbox = CAN_MBOX0;
} else if ((CAN_TSR(canport) & CAN_TSR_TME1) == CAN_TSR_TME1) {
ret = 1;
mailbox = CAN_MBOX1;
} else if ((CAN_TSR(canport) & CAN_TSR_TME2) == CAN_TSR_TME2) {
ret = 2;
mailbox = CAN_MBOX2;
} else {
ret = -1;
}
/* If we have no empty mailbox return with an error. */
if (ret == -1) {
return ret;
}
if (ext) {
/* Set extended ID. */
CAN_TIxR(canport, mailbox) = (id << CAN_TIxR_EXID_SHIFT) |
CAN_TIxR_IDE;
} else {
/* Set standard ID. */
CAN_TIxR(canport, mailbox) = id << CAN_TIxR_STID_SHIFT;
}
/* Set/clear remote transmission request bit. */
if (rtr) {
CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */
}
/* Set the DLC. */
CAN_TDTxR(canport, mailbox) &= ~CAN_TDTxR_DLC_MASK;
CAN_TDTxR(canport, mailbox) |= (length & CAN_TDTxR_DLC_MASK);
switch (length) {
case 8:
tdhxr.data8[3] = data[7];
/* no break */
case 7:
tdhxr.data8[2] = data[6];
/* no break */
case 6:
tdhxr.data8[1] = data[5];
/* no break */
case 5:
tdhxr.data8[0] = data[4];
/* no break */
case 4:
tdlxr.data8[3] = data[3];
/* no break */
case 3:
tdlxr.data8[2] = data[2];
/* no break */
case 2:
tdlxr.data8[1] = data[1];
/* no break */
case 1:
tdlxr.data8[0] = data[0];
/* no break */
default:
break;
}
/* Set the data. */
CAN_TDLxR(canport, mailbox) = tdlxr.data32;
CAN_TDHxR(canport, mailbox) = tdhxr.data32;
/* Request transmission. */
CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ;
return ret;
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Release FIFO
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] fifo Unsigned int8. FIFO id.
*/
void can_fifo_release(uint32_t canport, uint8_t fifo)
{
if (fifo == 0) {
CAN_RF0R(canport) |= CAN_RF1R_RFOM1;
} else {
CAN_RF1R(canport) |= CAN_RF1R_RFOM1;
}
}
/*---------------------------------------------------------------------------*/
/** @brief CAN Receive Message
@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
@param[in] fifo Unsigned int8. FIFO id.
@param[in] release bool. Release the FIFO automatically after coping data out.
@param[out] id Unsigned int32 pointer. Message ID.
@param[out] ext bool pointer. The message ID is extended?
@param[out] rtr bool pointer. Request of transmission?
@param[out] fmi Unsigned int32 pointer. ID of the matched filter.
@param[out] length Unsigned int8 pointer. Length of message payload.
@param[out] data Unsigned int8[]. Message payload data.
*/
void can_receive(uint32_t canport, uint8_t fifo, bool release, uint32_t *id,
bool *ext, bool *rtr, uint32_t *fmi, uint8_t *length,
uint8_t *data)
{
uint32_t fifo_id = 0;
union {
uint8_t data8[4];
uint32_t data32;
} rdlxr, rdhxr;
const uint32_t fifoid_array[2] = {CAN_FIFO0, CAN_FIFO1};
fifo_id = fifoid_array[fifo];
/* Get type of CAN ID and CAN ID. */
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
*ext = true;
/* Get extended CAN ID. */
*id = (CAN_RIxR(canport, fifo_id) >> CAN_RIxR_EXID_SHIFT) &
CAN_RIxR_EXID_MASK;
} else {
*ext = false;
/* Get standard CAN ID. */
*id = (CAN_RIxR(canport, fifo_id) >> CAN_RIxR_STID_SHIFT) &
CAN_RIxR_STID_MASK;
}
/* Get remote transmit flag. */
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR) {
*rtr = true;
} else {
*rtr = false;
}
/* Get filter match ID. */
*fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >>
CAN_RDTxR_FMI_SHIFT);
/* Get data length. */
*length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK;
/* accelerate reception by copying the CAN data from the controller
* memory to the fast internal RAM
*/
rdlxr.data32 = CAN_RDLxR(canport, fifo_id);
rdhxr.data32 = CAN_RDHxR(canport, fifo_id);
/* */
/* Get data.
* Byte wise copy is needed because we do not know the alignment
* of the input buffer.
* Here copying 8 bytes unconditionally is faster than using loop
*
* It is OK to copy all 8 bytes because the upper layer must be
* prepared for data length bigger expected.
* In contrary the driver has no information about the intended size.
* This could be different if the max length would be handed over
* to the function, but it is not the case
*/
data[0] = rdlxr.data8[0];
data[1] = rdlxr.data8[1];
data[2] = rdlxr.data8[2];
data[3] = rdlxr.data8[3];
data[4] = rdhxr.data8[0];
data[5] = rdhxr.data8[1];
data[6] = rdhxr.data8[2];
data[7] = rdhxr.data8[3];
/* Release the FIFO. */
if (release) {
can_fifo_release(canport, fifo);
}
}
bool can_available_mailbox(uint32_t canport)
{
return CAN_TSR(canport) & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
}

View File

@ -0,0 +1,81 @@
/** @addtogroup crc_file
@author @htmlonly &copy; @endhtmlonly 2012 Karl Palsson <karlp@remake.is>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@remake.is>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crc.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief CRC Reset.
Reset the CRC unit and forces the data register to all 1s.
*/
void crc_reset(void)
{
CRC_CR |= CRC_CR_RESET;
}
/*---------------------------------------------------------------------------*/
/** @brief CRC Calculate.
Writes a data word to the register, the write operation stalling until the
computation is complete.
@param[in] data Unsigned int32.
@returns int32 Computed CRC result
*/
uint32_t crc_calculate(uint32_t data)
{
CRC_DR = data;
/* Data sheet says this blocks until it's ready.... */
return CRC_DR;
}
/*---------------------------------------------------------------------------*/
/** @brief CRC Calculate of a Block of Data.
Writes data words consecutively to the register, the write operation stalling
until the computation of each word is complete.
@param[in] datap Unsigned int32. pointer to an array of 32 bit data words.
@param[in] size int. Size of the array.
@returns int32 Final computed CRC result
*/
uint32_t crc_calculate_block(uint32_t *datap, int size)
{
int i;
for (i = 0; i < size; i++) {
CRC_DR = datap[i];
}
return CRC_DR;
}
/**@}*/

View File

@ -0,0 +1,175 @@
/** @addtogroup crypto_file
*
* @brief <b>libopencm3 STM32 Cryptographic controller</b>
*
* @version 1.0.0
*
* @date 17 Jun 2013
*
* This library supports the cryptographic coprocessor system for the
* STM32 series of ARM Cortex Microcontrollers
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/crypto.h>
#define CRYP_CR_ALGOMODE_MASK ((1 << 19) | CRYP_CR_ALGOMODE)
/**
* @brief Wait, if the Controller is busy
*/
void crypto_wait_busy(void)
{
while (CRYP_SR & CRYP_SR_BUSY);
}
/**
* @brief Set key value to the controller
* @param[in] keysize enum crypto_keysize Specified size of the key.
* @param[in] key uint64_t[] Key value (array of 4 items)
*/
void crypto_set_key(enum crypto_keysize keysize, uint64_t key[])
{
int i;
crypto_wait_busy();
CRYP_CR = (CRYP_CR & ~CRYP_CR_KEYSIZE) |
(keysize << CRYP_CR_KEYSIZE_SHIFT);
for (i = 0; i < 4; i++) {
CRYP_KR(i) = key[i];
}
}
/**
* @brief Set Initialization Vector
*
* @param[in] iv uint64_t[] Initialization vector (array of 4 items)
* @note Cryptographic controller must be in disabled state
*/
void crypto_set_iv(uint64_t iv[])
{
int i;
crypto_wait_busy();
for (i = 0; i < 4; i++) {
CRYP_IVR(i) = iv[i];
}
}
/**
* @brief Set the order of the data to be crypted
*
* @param[in] datatype enum crypto_datatype Specified datatype of the key.
*/
void crypto_set_datatype(enum crypto_datatype datatype)
{
CRYP_CR = (CRYP_CR & ~CRYP_CR_DATATYPE) |
(datatype << CRYP_CR_DATATYPE_SHIFT);
}
/**
* @brief Set the algoritm for Encryption/decryption
*
*@param[in] mode enum crypto_mode Mode of execution
*/
void crypto_set_algorithm(enum crypto_mode mode)
{
mode &= ~CRYP_CR_ALGOMODE_MASK;
if ((mode == DECRYPT_AES_ECB) || (mode == DECRYPT_AES_CBC)) {
/* Unroll keys for the AES encoder for the user automatically */
CRYP_CR = (CRYP_CR & ~CRYP_CR_ALGOMODE_MASK) |
CRYP_CR_ALGOMODE_AES_PREP;
crypto_start();
crypto_wait_busy();
/* module switches to DISABLE automatically */
}
/* set algo mode */
CRYP_CR = (CRYP_CR & ~CRYP_CR_ALGOMODE_MASK) | mode;
/* flush buffers */
CRYP_CR |= CRYP_CR_FFLUSH;
}
/**
* @brief Enable the cryptographic controller and start processing
*/
void crypto_start(void)
{
CRYP_CR |= CRYP_CR_CRYPEN;
}
/**
* @brief Disable the cryptographic controller and stop processing
*/
void crypto_stop(void)
{
CRYP_CR &= ~CRYP_CR_CRYPEN;
}
/**
* @brief Start of encryption or decryption on data buffers
*
* This blocking method transfers input buffer of specified length to the
* cryptographic coprocessor, and instructs him to begin of ciphering or
* deciphering. It waits for data to be ready, and then fills the processed
* data to output buffer.
*
* @param[in] inp uint32_t* Input array to crypt/decrypt.
* @param[in] outp uint32_t* Output array with crypted/encrypted data.
* @param[in] length uint32_t Length of the arrays
*
* @returns uint32_t Number of written words
*/
uint32_t crypto_process_block(uint32_t *inp, uint32_t *outp, uint32_t length)
{
uint32_t rd = 0, wr = 0;
/* Transfer the data */
while (rd != length) {
if ((wr < length) && (CRYP_SR & CRYP_SR_IFNF)) {
CRYP_DIN = *inp++;
wr++;
}
if (CRYP_SR & CRYP_SR_OFNE) {
*outp++ = CRYP_DOUT;
rd++;
}
}
/* Wait to finish - Not needed ? */
crypto_wait_busy();
return wr;
}
/**@}*/

View File

@ -0,0 +1,500 @@
/** @addtogroup dac_file
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies ksarkies@internode.on.net
This library supports the Digital to Analog Conversion System in the
STM32F series of ARM Cortex Microcontrollers by ST Microelectronics.
The DAC is present only in a limited set of devices, notably some
of the connection line, high density and XL devices.
Two DAC channels are available, however unlike the ADC channels these
are separate DAC devices controlled by the same register block.
The DAC is on APB1. Its clock must be enabled in RCC and the GPIO
ports set to alternate function output before it can be used.
The digital output driver is disabled so the output driver mode
(push-pull/open drain) is arbitrary.
The DAC has a holding (buffer) register and an output register from
which the analog output is derived. The holding register must be
loaded first. If triggering is enabled the output register is loaded
from the holding register after a trigger occurs. If triggering is
not enabled the holding register contents are transferred directly
to the output register.
@note To avoid nonlinearities, do not allow outputs to range close
to zero or V_analog.
@section dac_api_dual Dual Channel Conversion
There are dual modes in which both DACs are used to output data
simultaneously or independently on both channels. The data must be
presented according to the formats described in the datasheets. A
convenience function @ref dac_load_data_buffer_dual is provided
for software controlled use.
A variety of modes are available depending on whether independent
or simultaneous output is desired, and whether waveforms are to be
superimposed. Refer to the datasheets.
If DMA is used, only enable it for one of the channels. The DMA
requests will then serve data in dual format to the data register
dedicated to dual mode. The data will then be split and loaded to the
appropriate DAC following the next trigger. There are three registers
available, one for each of the formats: 12 bit right-aligned, 12 bit
left-aligned and 8 bit right-aligned. The desired format is determined
by specifying the appropriate register to the DMA controller.
@section dac_api_basic_ex Basic DAC handling API.
Set the DAC's GPIO port to any alternate function output mode. Enable the
DAC clock. Enable the DAC, set a trigger source and load the buffer
with the first value. After the DAC is triggered, load the buffer with
the next value. This example uses software triggering and added noise.
The trigger and further buffer load calls are made when data is to be
sent out.
@code
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_DACEN);
dac_disable(CHANNEL_1);
dac_set_waveform_characteristics(DAC_CR_MAMP1_8);
dac_set_waveform_generation(DAC_CR_WAVE1_NOISE);
dac_enable(CHANNEL_1);
dac_set_trigger_source(DAC_CR_TSEL1_SW);
dac_load_data_buffer_single(0, RIGHT12, CHANNEL_1);
....
dac_software_trigger(CHANNEL_1);
dac_load_data_buffer_single(value, RIGHT12, CHANNEL_1);
@endcode
@section dac_api_dma_ex Simultaneous Dual DAC with DMA.
This example in part sets up the DAC channel 1 DMA (DMA2 channel 3) to read
16 bit data from memory into the right-aligned 8 bit dual register DAC_DHR8RD.
Both DAC channels are enabled, and both triggers are set to the same timer
2 input as required for simultaneous operation. DMA is enabled for DAC channel
1 only to ensure that only one DMA request is generated.
@code
dma_set_memory_size(DMA2,DMA_CHANNEL3,DMA_CCR_MSIZE_16BIT);
dma_set_peripheral_size(DMA2,DMA_CHANNEL3,DMA_CCR_PSIZE_16BIT);
dma_set_read_from_memory(DMA2,DMA_CHANNEL3);
dma_set_peripheral_address(DMA2,DMA_CHANNEL3,(uint32_t) &DAC_DHR8RD);
dma_enable_channel(DMA2,DMA_CHANNEL3);
...
dac_trigger_enable(CHANNEL_D);
dac_set_trigger_source(DAC_CR_TSEL1_T2 | DAC_CR_TSEL2_T2);
dac_dma_enable(CHANNEL_1);
dac_enable(CHANNEL_D);
@endcode
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/dac.h>
#define MASK8 0xFF
#define MASK12 0xFFF
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel Enable.
Enable a digital to analog converter channel. After setting this enable, the
DAC requires a t<sub>wakeup</sub> time typically around 10 microseconds before
it actually wakes up.
@param[in] dac_channel enum ::data_channel.
*/
void dac_enable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR |= DAC_CR_EN1;
break;
case CHANNEL_2:
DAC_CR |= DAC_CR_EN2;
break;
case CHANNEL_D:
DAC_CR |= (DAC_CR_EN1 | DAC_CR_EN2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel Disable.
Disable a digital to analog converter channel.
@param[in] dac_channel enum ::data_channel.
*/
void dac_disable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR &= ~DAC_CR_EN1;
break;
case CHANNEL_2:
DAC_CR &= ~DAC_CR_EN2;
break;
case CHANNEL_D:
DAC_CR &= ~(DAC_CR_EN1 | DAC_CR_EN2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel Output Buffer Enable.
Enable a digital to analog converter channel output drive buffer. This is an
optional amplifying buffer that provides additional drive for the output
signal. The buffer is enabled by default after a reset and needs to be
explicitly disabled if required.
@param[in] dac_channel enum ::data_channel.
*/
void dac_buffer_enable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR |= DAC_CR_BOFF1;
break;
case CHANNEL_2:
DAC_CR |= DAC_CR_BOFF2;
break;
case CHANNEL_D:
DAC_CR |= (DAC_CR_BOFF1 | DAC_CR_BOFF2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel Output Buffer Disable.
Disable a digital to analog converter channel output drive buffer. Disabling
this will reduce power consumption slightly and will increase the output
impedance of the DAC. The buffers are enabled by default after a reset.
@param[in] dac_channel enum ::data_channel.
*/
void dac_buffer_disable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR &= ~DAC_CR_BOFF1;
break;
case CHANNEL_2:
DAC_CR &= ~DAC_CR_BOFF2;
break;
case CHANNEL_D:
DAC_CR &= ~(DAC_CR_BOFF1 | DAC_CR_BOFF2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel DMA Enable.
Enable a digital to analog converter channel DMA mode (connected to DMA2 channel
3 for DAC channel 1 and DMA2 channel 4 for DAC channel 2). A DMA request is
generated following an external trigger.
@param[in] dac_channel enum ::data_channel.
*/
void dac_dma_enable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR |= DAC_CR_DMAEN1;
break;
case CHANNEL_2:
DAC_CR |= DAC_CR_DMAEN2;
break;
case CHANNEL_D:
DAC_CR |= (DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel DMA Disable.
Disable a digital to analog converter channel DMA mode.
@param[in] dac_channel enum ::data_channel.
*/
void dac_dma_disable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR &= ~DAC_CR_DMAEN1;
break;
case CHANNEL_2:
DAC_CR &= ~DAC_CR_DMAEN2;
break;
case CHANNEL_D:
DAC_CR &= ~(DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel Trigger Enable.
Enable a digital to analog converter channel external trigger mode. This allows
an external trigger to initiate register transfers from the buffer register to
the DAC output register, followed by a DMA transfer to the buffer register if
DMA is enabled. The trigger source must also be selected.
@param[in] dac_channel enum ::data_channel.
*/
void dac_trigger_enable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR |= DAC_CR_TEN1;
break;
case CHANNEL_2:
DAC_CR |= DAC_CR_TEN2;
break;
case CHANNEL_D:
DAC_CR |= (DAC_CR_TEN1 | DAC_CR_TEN2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DAC Channel Trigger Disable.
Disable a digital to analog converter channel external trigger.
@param[in] dac_channel enum ::data_channel.
*/
void dac_trigger_disable(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR &= ~DAC_CR_TEN1;
break;
case CHANNEL_2:
DAC_CR &= ~DAC_CR_TEN2;
break;
case CHANNEL_D:
DAC_CR &= ~(DAC_CR_TEN1 | DAC_CR_TEN2);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Set DAC Channel Trigger Source.
Sets the digital to analog converter trigger source, which can be taken from
various timers, an external trigger or a software trigger.
@param[in] dac_trig_src uint32_t. Taken from @ref dac_trig2_sel or @ref
dac_trig1_sel or a logical OR of one of each of these to set both channels
simultaneously.
*/
void dac_set_trigger_source(uint32_t dac_trig_src)
{
DAC_CR |= dac_trig_src;
}
/*---------------------------------------------------------------------------*/
/** @brief Enable and Set DAC Channel Waveform Generation.
Enable the digital to analog converter waveform generation as either
pseudo-random noise or triangular wave. These signals are superimposed on
existing output values in the DAC output registers.
@note The DAC trigger must be enabled for this to work.
@param[in] dac_wave_ens uint32_t. Taken from @ref dac_wave1_en or @ref
dac_wave2_en or a logical OR of one of each of these to set both channels
simultaneously.
*/
void dac_set_waveform_generation(uint32_t dac_wave_ens)
{
DAC_CR |= dac_wave_ens;
}
/*---------------------------------------------------------------------------*/
/** @brief Disable DAC Channel Waveform Generation.
Disable a digital to analog converter channel superimposed waveform generation.
@param[in] dac_channel enum ::data_channel.
*/
void dac_disable_waveform_generation(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_CR &= ~DAC_CR_WAVE1_DIS;
break;
case CHANNEL_2:
DAC_CR &= ~DAC_CR_WAVE2_DIS;
break;
case CHANNEL_D:
DAC_CR &= ~(DAC_CR_WAVE1_DIS | DAC_CR_WAVE2_DIS);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Set DAC Channel LFSR Mask or Triangle Wave Amplitude.
Sets the digital to analog converter superimposed waveform generation
characteristics. @li If the noise generation mode is set, this sets the length
of the PRBS sequence and hence the amplitude of the output noise signal.
Default setting is length 1. @li If the triangle wave generation mode is set,
this sets the amplitude of the output signal as 2^(n)-1 where n is the
parameter value. Default setting is 1.
@note High amplitude levels of these waveforms can overload the DAC and distort
the signal output.
@note This must be called before enabling the DAC as the settings will then
become read-only.
@note The DAC trigger must be enabled for this to work.
@param[in] dac_mamp uint32_t. Taken from @ref dac_mamp2 or @ref dac_mamp1 or a
logical OR of one of each of these to set both channels simultaneously.
*/
void dac_set_waveform_characteristics(uint32_t dac_mamp)
{
DAC_CR |= dac_mamp;
}
/*---------------------------------------------------------------------------*/
/** @brief Load DAC Data Register.
Loads the appropriate digital to analog converter data register with 12 or 8 bit
data to be converted on a channel. The data can be aligned as follows:
@li right-aligned 8 bit data in bits 0-7
@li right-aligned 12 bit data in bits 0-11
@li left aligned 12 bit data in bits 4-15
@param[in] dac_data uint16_t with appropriate alignment.
@param[in] dac_data_format enum ::data_align. Alignment and size.
@param[in] dac_channel enum ::data_channel.
*/
void dac_load_data_buffer_single(uint16_t dac_data, data_align dac_data_format,
data_channel dac_channel)
{
if (dac_channel == CHANNEL_1) {
switch (dac_data_format) {
case RIGHT8:
DAC_DHR8R1 = dac_data;
break;
case RIGHT12:
DAC_DHR12R1 = dac_data;
break;
case LEFT12:
DAC_DHR12L1 = dac_data;
break;
}
} else if (dac_channel == CHANNEL_2) {
switch (dac_data_format) {
case RIGHT8:
DAC_DHR8R2 = dac_data;
break;
case RIGHT12:
DAC_DHR12R2 = dac_data;
break;
case LEFT12:
DAC_DHR12L2 = dac_data;
break;
}
}
}
/*---------------------------------------------------------------------------*/
/** @brief Load DAC Dual Data Register.
Loads the appropriate digital to analog converter dual data register with 12 or
8 bit data to be converted for both channels. This allows high bandwidth
simultaneous or independent analog output. The data in both channels are aligned
identically.
@param[in] dac_data1 uint16_t for channel 1 with appropriate alignment.
@param[in] dac_data2 uint16_t for channel 2 with appropriate alignment.
@param[in] dac_data_format enum ::data_align. Right or left aligned, and 8 or
12 bit.
*/
void dac_load_data_buffer_dual(uint16_t dac_data1, uint16_t dac_data2,
data_align dac_data_format)
{
switch (dac_data_format) {
case RIGHT8:
DAC_DHR8RD = ((dac_data1 & MASK8) | ((dac_data2 & MASK8) << 8));
break;
case RIGHT12:
DAC_DHR12RD = ((dac_data1 & MASK12) |
((dac_data2 & MASK12) << 16));
break;
case LEFT12:
DAC_DHR12LD = ((dac_data1 & MASK12) |
((dac_data2 & MASK12) << 16));
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Trigger the DAC by a Software Trigger.
If the trigger source is set to be a software trigger, cause a trigger to occur.
The trigger is cleared by hardware after conversion.
@param[in] dac_channel enum ::data_channel.
*/
void dac_software_trigger(data_channel dac_channel)
{
switch (dac_channel) {
case CHANNEL_1:
DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG1;
break;
case CHANNEL_2:
DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG2;
break;
case CHANNEL_D:
DAC_SWTRIGR |= (DAC_SWTRIGR_SWTRIG1 | DAC_SWTRIGR_SWTRIG2);
break;
}
}
/**@}*/

View File

@ -0,0 +1,794 @@
/** @addtogroup dma_file
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
This library supports the DMA Control System in the STM32F2 and STM32F4
series of ARM Cortex Microcontrollers by ST Microelectronics.
Up to two DMA controllers are supported each with 8 streams, and each stream
having up to 8 channels hardware dedicated to various peripheral DMA signals.
DMA transfers can be configured to occur between peripheral and memory in
either direction, and memory to memory. Peripheral to peripheral transfer
is not supported. Circular mode transfers are also supported in transfers
involving a peripheral. An arbiter is provided to resolve priority DMA
requests. Transfers can be made with 8, 16 or 32 bit words.
Each stream has access to a 4 word deep FIFO and can use double buffering
by means of two memory pointers. When using the FIFO it is possible to
configure transfers to occur in indivisible bursts.
It is also possible to select a peripheral instead of the DMA controller to
control the flow of data. This limits the functionality but is useful when the
number of transfers is unknown.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/dma.h>
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Reset
The specified stream is disabled and configuration registers are cleared.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_stream_reset(uint32_t dma, uint8_t stream)
{
/* Disable stream (must be done before register is otherwise changed). */
DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;
/* Reset all config bits. */
DMA_SCR(dma, stream) = 0;
/* Reset data transfer number. */
DMA_SNDTR(dma, stream) = 0;
/* Reset peripheral and memory addresses. */
DMA_SPAR(dma, stream) = 0;
DMA_SM0AR(dma, stream) = 0;
DMA_SM1AR(dma, stream) = 0;
/* This is the default setting */
DMA_SFCR(dma, stream) = 0x21;
/* Reset all stream interrupt flags using the interrupt flag clear register. */
uint32_t mask = DMA_ISR_MASK(stream);
if (stream < 4) {
DMA_LIFCR(dma) |= mask;
} else {
DMA_HIFCR(dma) |= mask;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Clear Interrupt Flag
The interrupt flag for the stream is cleared. More than one interrupt for the
same stream may be cleared by using the bitwise OR of the interrupt flags.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] interrupts unsigned int32. Bitwise OR of interrupt numbers: @ref
dma_if_offset
*/
void dma_clear_interrupt_flags(uint32_t dma, uint8_t stream,
uint32_t interrupts)
{
/* Get offset to interrupt flag location in stream field */
uint32_t flags = (interrupts << DMA_ISR_OFFSET(stream));
/* First four streams are in low register. Flag clear must be set then
* reset.
*/
if (stream < 4) {
DMA_LIFCR(dma) = flags;
} else {
DMA_HIFCR(dma) = flags;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Read Interrupt Flag
The interrupt flag for the stream is returned.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] interrupt unsigned int32. Interrupt number: @ref dma_if_offset
@returns bool interrupt flag is set.
*/
bool dma_get_interrupt_flag(uint32_t dma, uint8_t stream, uint32_t interrupt)
{
/* get offset to interrupt flag location in stream field. Assumes
* stream and interrupt parameters are integers.
*/
uint32_t flag = (interrupt << DMA_ISR_OFFSET(stream));
/* First four streams are in low register */
if (stream < 4) {
return ((DMA_LISR(dma) & flag) > 0);
} else {
return ((DMA_HISR(dma) & flag) > 0);
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Transfer Direction
Set peripheral to memory, memory to peripheral or memory to memory. If memory
to memory mode is selected, circular mode and double buffer modes are disabled.
Ensure that these modes are not enabled at a later time.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] direction unsigned int32. Data transfer direction @ref dma_st_dir
*/
void dma_set_transfer_mode(uint32_t dma, uint8_t stream, uint32_t direction)
{
uint32_t reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_DIR_MASK);
/* Disable circular and double buffer modes if memory to memory
* transfers are in effect. (Direct Mode is automatically disabled by
* hardware)
*/
if (direction == DMA_SxCR_DIR_MEM_TO_MEM) {
reg32 &= ~(DMA_SxCR_CIRC | DMA_SxCR_DBM);
}
DMA_SCR(dma, stream) = (reg32 | direction);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Priority
Stream Priority has four levels: low to very high. This has precedence over the
hardware priority. In the event of equal software priority the lower numbered
stream has priority.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] prio unsigned int32. Priority level @ref dma_st_pri.
*/
void dma_set_priority(uint32_t dma, uint8_t stream, uint32_t prio)
{
DMA_SCR(dma, stream) &= ~(DMA_SxCR_PL_MASK);
DMA_SCR(dma, stream) |= prio;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Memory Word Width
Set the memory word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
alignment information if the source and destination widths do not match.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] mem_size unsigned int32. Memory word width @ref dma_st_memwidth.
*/
void dma_set_memory_size(uint32_t dma, uint8_t stream, uint32_t mem_size)
{
DMA_SCR(dma, stream) &= ~(DMA_SxCR_MSIZE_MASK);
DMA_SCR(dma, stream) |= mem_size;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Peripheral Word Width
Set the peripheral word width 8 bits, 16 bits, or 32 bits. Refer to datasheet
for alignment information if the source and destination widths do not match, or
if the peripheral does not support byte or half-word writes.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] peripheral_size unsigned int32. Peripheral word width @ref
dma_st_perwidth.
*/
void dma_set_peripheral_size(uint32_t dma, uint8_t stream,
uint32_t peripheral_size)
{
DMA_SCR(dma, stream) &= ~(DMA_SxCR_PSIZE_MASK);
DMA_SCR(dma, stream) |= peripheral_size;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Memory Increment after Transfer
Following each transfer the current memory address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_memory_size. The
value held by the base memory address register is unchanged.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_memory_increment_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) |= DMA_SxCR_MINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Memory Increment after Transfer
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_memory_increment_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_MINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Variable Sized Peripheral Increment after Transfer
Following each transfer the current peripheral address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
value held by the base peripheral address register is unchanged.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_peripheral_increment_mode(uint32_t dma, uint8_t stream)
{
uint32_t reg32 = (DMA_SCR(dma, stream) | DMA_SxCR_PINC);
DMA_SCR(dma, stream) = (reg32 & ~DMA_SxCR_PINCOS);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Peripheral Increment after Transfer
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_peripheral_increment_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_PINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Fixed Sized Peripheral Increment after Transfer
Following each transfer the current peripheral address is incremented by
4 regardless of the data size. The value held by the base peripheral address
register is unchanged.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_fixed_peripheral_increment_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) |= (DMA_SxCR_PINC | DMA_SxCR_PINCOS);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Memory Circular Mode
After the number of bytes/words to be transferred has been completed, the
original transfer block size, memory and peripheral base addresses are
reloaded and the process repeats.
Ensure that the stream is disabled otherwise the setting will not be changed.
@note This cannot be used with memory to memory mode. It is disabled
automatically if the peripheral is selected as the flow controller.
It is enabled automatically if double buffered mode is selected.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_circular_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) |= DMA_SxCR_CIRC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Channel Select
Associate an input channel to the stream. Not every channel is allocated to a
hardware DMA request signal. The allocations for each stream are given in the
STM32F4 Reference Manual.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] channel unsigned int8. Channel selection @ref dma_ch_sel
*/
void dma_channel_select(uint32_t dma, uint8_t stream, uint32_t channel)
{
DMA_SCR(dma, stream) |= channel;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Memory Burst Configuration
Set the memory burst type to none, 4 8 or 16 word length. This is forced to none
if direct mode is used.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] burst unsigned int8. Memory Burst selection @ref dma_mburst
*/
void dma_set_memory_burst(uint32_t dma, uint8_t stream, uint32_t burst)
{
uint32_t reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_MBURST_MASK);
DMA_SCR(dma, stream) = (reg32 | burst);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Peripheral Burst Configuration
Set the memory burst type to none, 4 8 or 16 word length. This is forced to none
if direct mode is used.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] burst unsigned int8. Peripheral Burst selection @ref dma_pburst
*/
void dma_set_peripheral_burst(uint32_t dma, uint8_t stream, uint32_t burst)
{
uint32_t reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_PBURST_MASK);
DMA_SCR(dma, stream) = (reg32 | burst);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Initial Target Memory
In double buffered mode, set the target memory (M0 or M1) to be used for the
first transfer.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] memory unsigned int8. Initial memory pointer to use: 0 or 1
*/
void dma_set_initial_target(uint32_t dma, uint8_t stream, uint8_t memory)
{
uint32_t reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_CT);
if (memory == 1) {
reg32 |= DMA_SxCR_CT;
}
DMA_SCR(dma, stream) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Read Current Memory Target
In double buffer mode, return the current memory target (M0 or M1). It is
possible to update the memory pointer in the register that is <b> not </b>
currently in use. An attempt to change the register currently in use will cause
the stream to be disabled and the transfer error flag to be set.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@returns unsigned int8. Memory buffer in use: 0 or 1
*/
uint8_t dma_get_target(uint32_t dma, uint8_t stream)
{
if (DMA_SCR(dma, stream) & DMA_SxCR_CT) {
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Double Buffer Mode
Double buffer mode is used for memory to/from peripheral transfers only, and in
circular mode which is automatically enabled. Two memory buffers must be
established with pointers stored in the memory pointer registers.
Ensure that the stream is disabled otherwise the setting will not be changed.
@note This cannot be used with memory to memory mode.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_double_buffer_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) |= DMA_SxCR_DBM;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Double Buffer Mode
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_double_buffer_mode(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_DBM;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set Peripheral Flow Control
Set the peripheral to control DMA flow. Useful when the number of transfers is
unknown. This is forced off when memory to memory mode is selected.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_set_peripheral_flow_control(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) |= DMA_SxCR_PFCTRL;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set DMA Flow Control
Set the DMA controller to control DMA flow. This is the default.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_set_dma_flow_control(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_PFCTRL;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Transfer Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_transfer_error_interrupt(uint32_t dma, uint8_t stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_TEIF);
DMA_SCR(dma, stream) |= DMA_SxCR_TEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Transfer Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_transfer_error_interrupt(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_TEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Transfer Half Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_half_transfer_interrupt(uint32_t dma, uint8_t stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_HTIF);
DMA_SCR(dma, stream) |= DMA_SxCR_HTIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Transfer Half Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_half_transfer_interrupt(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_HTIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Transfer Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_transfer_complete_interrupt(uint32_t dma, uint8_t stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_TCIF);
DMA_SCR(dma, stream) |= DMA_SxCR_TCIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Transfer Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_transfer_complete_interrupt(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_TCIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Direct Mode Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_direct_mode_error_interrupt(uint32_t dma, uint8_t stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_DMEIF);
DMA_SCR(dma, stream) |= DMA_SxCR_DMEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Direct Mode Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_direct_mode_error_interrupt(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_DMEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Enable Interrupt on FIFO Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_fifo_error_interrupt(uint32_t dma, uint8_t stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_FEIF);
DMA_SFCR(dma, stream) |= DMA_SxFCR_FEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Disable Interrupt on FIFO Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_fifo_error_interrupt(uint32_t dma, uint8_t stream)
{
DMA_SFCR(dma, stream) &= ~DMA_SxFCR_FEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Get FIFO Status
Status of FIFO (empty. full or partial filled states) is returned. This has no
meaning if direct mode is enabled (as the FIFO is not used).
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@returns uint32_t FIFO Status @ref dma_fifo_status
*/
uint32_t dma_fifo_status(uint32_t dma, uint8_t stream)
{
return DMA_SFCR(dma, stream) & DMA_SxFCR_FS_MASK;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Enable Direct Mode
Direct mode is the default. Data is transferred as soon as a DMA request is
received. The FIFO is not used. This must not be set when memory to memory
mode is selected.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_direct_mode(uint32_t dma, uint8_t stream)
{
DMA_SFCR(dma, stream) &= ~DMA_SxFCR_DMDIS;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Enable FIFO Mode
Data is transferred via a FIFO.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_fifo_mode(uint32_t dma, uint8_t stream)
{
DMA_SFCR(dma, stream) |= DMA_SxFCR_DMDIS;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Set FIFO Threshold
This is the filled level at which data is transferred out of the FIFO to the
destination.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] threshold unsigned int8. Threshold setting @ref dma_fifo_thresh
*/
void dma_set_fifo_threshold(uint32_t dma, uint8_t stream, uint32_t threshold)
{
uint32_t reg32 = (DMA_SFCR(dma, stream) & ~DMA_SxFCR_FTH_MASK);
DMA_SFCR(dma, stream) = (reg32 | threshold);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Enable
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_stream(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) |= DMA_SxCR_EN;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Disable
@note The DMA stream registers retain their values when the stream is disabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_stream(uint32_t dma, uint8_t stream)
{
DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Peripheral Address
Set the address of the peripheral register to or from which data is to be
transferred. Refer to the documentation for the specific peripheral.
@note The DMA stream must be disabled before setting this address. This function
has no effect if the stream is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] address unsigned int32. Peripheral Address.
*/
void dma_set_peripheral_address(uint32_t dma, uint8_t stream, uint32_t address)
{
if (!(DMA_SCR(dma, stream) & DMA_SxCR_EN)) {
DMA_SPAR(dma, stream) = (uint32_t *) address;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Base Memory Address 0
Set the address pointer to the memory location for DMA transfers. The DMA stream
must normally be disabled before setting this address, however it is possible
to change this in double buffer mode when the current target is memory area 1
(see @ref dma_get_target).
This is the default base memory address used in direct mode.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] address unsigned int32. Memory Initial Address.
*/
void dma_set_memory_address(uint32_t dma, uint8_t stream, uint32_t address)
{
uint32_t reg32 = DMA_SCR(dma, stream);
if (!(reg32 & DMA_SxCR_EN) ||
((reg32 & DMA_SxCR_CT) && (reg32 & DMA_SxCR_DBM))) {
DMA_SM0AR(dma, stream) = (uint32_t *) address;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Base Memory Address 1
Set the address pointer to the memory location for DMA transfers. The DMA stream
must normally be disabled before setting this address, however it is possible
to change this in double buffer mode when the current target is memory area 0
(see @ref dma_get_target).
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] address unsigned int32. Memory Initial Address.
*/
void dma_set_memory_address_1(uint32_t dma, uint8_t stream, uint32_t address)
{
uint32_t reg32 = DMA_SCR(dma, stream);
if (!(reg32 & DMA_SxCR_EN) ||
(!(reg32 & DMA_SxCR_CT) && (reg32 & DMA_SxCR_DBM))) {
DMA_SM1AR(dma, stream) = (uint32_t *) address;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Transfer Block Size
@note The DMA stream must be disabled before setting this count value. The count
is not changed if the stream is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] number unsigned int16. Number of data words to transfer (65535
maximum).
*/
void dma_set_number_of_data(uint32_t dma, uint8_t stream, uint16_t number)
{
DMA_SNDTR(dma, stream) = number;
}
/**@}*/

View File

@ -0,0 +1,435 @@
/** @addtogroup dma_file
@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
This library supports the DMA Control System in the STM32 series of ARM Cortex
Microcontrollers by ST Microelectronics.
Up to two DMA controllers are supported. 12 DMA channels are allocated 7 to
the first DMA controller and 5 to the second. Each channel is connected to
between 3 and 6 hardware peripheral DMA signals in a logical OR arrangement.
DMA transfers can be configured to occur between peripheral and memory in
any combination including memory to memory. Circular mode transfers are
also supported in transfers involving a peripheral. An arbiter is provided
to resolve priority DMA requests. Transfers can be made with 8, 16 or 32 bit
words.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/dma.h>
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Reset
The channel is disabled and configuration registers are cleared.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_channel_reset(uint32_t dma, uint8_t channel)
{
/* Disable channel and reset config bits. */
DMA_CCR(dma, channel) = 0;
/* Reset data transfer number. */
DMA_CNDTR(dma, channel) = 0;
/* Reset peripheral address. */
DMA_CPAR(dma, channel) = 0;
/* Reset memory address. */
DMA_CMAR(dma, channel) = 0;
/* Reset interrupt flags. */
DMA_IFCR(dma) |= DMA_IFCR_CIF(channel);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Clear Interrupt Flag
The interrupt flag for the channel is cleared. More than one interrupt for the
same channel may be cleared by using the logical OR of the interrupt flags.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: @ref dma_ch
@param[in] interrupts unsigned int32. Logical OR of interrupt numbers: @ref
dma_if_offset
*/
void dma_clear_interrupt_flags(uint32_t dma, uint8_t channel,
uint32_t interrupts)
{
/* Get offset to interrupt flag location in channel field */
uint32_t flags = (interrupts << DMA_FLAG_OFFSET(channel));
DMA_IFCR(dma) = flags;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Read Interrupt Flag
The interrupt flag for the channel is returned.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: @ref dma_ch
@param[in] interrupt unsigned int32. Interrupt number: @ref dma_if_offset
@returns bool interrupt flag is set.
*/
bool dma_get_interrupt_flag(uint32_t dma, uint8_t channel, uint32_t interrupt)
{
/* get offset to interrupt flag location in channel field. */
uint32_t flag = (interrupt << DMA_FLAG_OFFSET(channel));
return ((DMA_ISR(dma) & flag) > 0);
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory to Memory Transfers
Memory to memory transfers do not require a trigger to activate each transfer.
Transfers begin immediately the channel has been enabled, and proceed without
intervention.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_mem2mem_mode(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_MEM2MEM;
DMA_CCR(dma, channel) &= ~DMA_CCR_CIRC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Set Priority
Channel Priority has four levels: low to very high. This has precedence over the
hardware priority.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
@param[in] prio unsigned int32. Priority level @ref dma_ch_pri.
*/
void dma_set_priority(uint32_t dma, uint8_t channel, uint32_t prio)
{
DMA_CCR(dma, channel) &= ~(DMA_CCR_PL_MASK);
DMA_CCR(dma, channel) |= prio;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Set Memory Word Width
Set the memory word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
alignment information if the source and destination widths do not match.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
@param[in] mem_size unsigned int32. Memory word width @ref dma_ch_memwidth.
*/
void dma_set_memory_size(uint32_t dma, uint8_t channel, uint32_t mem_size)
{
DMA_CCR(dma, channel) &= ~(DMA_CCR_MSIZE_MASK);
DMA_CCR(dma, channel) |= mem_size;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Set Peripheral Word Width
Set the peripheral word width 8 bits, 16 bits, or 32 bits. Refer to datasheet
for alignment information if the source and destination widths do not match, or
if the peripheral does not support byte or half-word writes.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
@param[in] peripheral_size unsigned int32. Peripheral word width @ref
dma_ch_perwidth.
*/
void dma_set_peripheral_size(uint32_t dma, uint8_t channel,
uint32_t peripheral_size)
{
DMA_CCR(dma, channel) &= ~(DMA_CCR_PSIZE_MASK);
DMA_CCR(dma, channel) |= peripheral_size;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory Increment after Transfer
Following each transfer the current memory address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_memory_size. The
value held by the base memory address register is unchanged.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_memory_increment_mode(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_MINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Memory Increment after Transfer
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_memory_increment_mode(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_MINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Peripheral Increment after Transfer
Following each transfer the current peripheral address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
value held by the base peripheral address register is unchanged.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_peripheral_increment_mode(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_PINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Peripheral Increment after Transfer
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_peripheral_increment_mode(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_PINC;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory Circular Mode
After the number of bytes/words to be transferred has been completed, the
original transfer block size, memory and peripheral base addresses are
reloaded and the process repeats.
@note This cannot be used with memory to memory mode, which is explictly
disabled here.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_circular_mode(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_CIRC;
DMA_CCR(dma, channel) &= ~DMA_CCR_MEM2MEM;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Transfers from a Peripheral
The data direction is set to read from a peripheral.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_set_read_from_peripheral(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_DIR;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Transfers from Memory
The data direction is set to read from memory.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_set_read_from_memory(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_DIR;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Interrupt on Transfer Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_transfer_error_interrupt(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_TEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Interrupt on Transfer Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_transfer_error_interrupt(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_TEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Interrupt on Transfer Half Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_half_transfer_interrupt(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_HTIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Interrupt on Transfer Half Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_half_transfer_interrupt(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_HTIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Interrupt on Transfer Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_transfer_complete_interrupt(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_TCIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Interrupt on Transfer Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_transfer_complete_interrupt(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_TCIE;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Enable
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_channel(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_EN;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Disable
@note The DMA channel registers retain their values when the channel is
disabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_channel(uint32_t dma, uint8_t channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_EN;
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Set the Peripheral Address
Set the address of the peripheral register to or from which data is to be
transferred. Refer to the documentation for the specific peripheral.
@note The DMA channel must be disabled before setting this address. This
function has no effect if the channel is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
@param[in] address unsigned int32. Peripheral Address.
*/
void dma_set_peripheral_address(uint32_t dma, uint8_t channel, uint32_t address)
{
if (!(DMA_CCR(dma, channel) & DMA_CCR_EN)) {
DMA_CPAR(dma, channel) = (uint32_t) address;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Set the Base Memory Address
@note The DMA channel must be disabled before setting this address. This
function has no effect if the channel is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
@param[in] address unsigned int32. Memory Initial Address.
*/
void dma_set_memory_address(uint32_t dma, uint8_t channel, uint32_t address)
{
if (!(DMA_CCR(dma, channel) & DMA_CCR_EN)) {
DMA_CMAR(dma, channel) = (uint32_t) address;
}
}
/*---------------------------------------------------------------------------*/
/** @brief DMA Channel Set the Transfer Block Size
@note The DMA channel must be disabled before setting this count value. The
count is not changed if the channel is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
@param[in] number unsigned int16. Number of data words to transfer (65535
maximum).
*/
void dma_set_number_of_data(uint32_t dma, uint8_t channel, uint16_t number)
{
DMA_CNDTR(dma, channel) = number;
}
/**@}*/

View File

@ -0,0 +1,151 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* This provides the code for the "next gen" EXTI block provided in F2/F4/L1
* devices. (differences only in the source selection)
*/
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/gpio.h>
#if !defined(AFIO_BASE)
# include <libopencm3/stm32/syscfg.h>
#endif
void exti_set_trigger(uint32_t extis, enum exti_trigger_type trig)
{
switch (trig) {
case EXTI_TRIGGER_RISING:
EXTI_RTSR |= extis;
EXTI_FTSR &= ~extis;
break;
case EXTI_TRIGGER_FALLING:
EXTI_RTSR &= ~extis;
EXTI_FTSR |= extis;
break;
case EXTI_TRIGGER_BOTH:
EXTI_RTSR |= extis;
EXTI_FTSR |= extis;
break;
}
}
void exti_enable_request(uint32_t extis)
{
/* Enable interrupts. */
EXTI_IMR |= extis;
/* Enable events. */
EXTI_EMR |= extis;
}
void exti_disable_request(uint32_t extis)
{
/* Disable interrupts. */
EXTI_IMR &= ~extis;
/* Disable events. */
EXTI_EMR &= ~extis;
}
/*
* Reset the interrupt request by writing a 1 to the corresponding
* pending bit register.
*/
void exti_reset_request(uint32_t extis)
{
EXTI_PR = extis;
}
/*
* Check the flag of a given EXTI interrupt.
* */
uint32_t exti_get_flag_status(uint32_t exti)
{
return EXTI_PR & exti;
}
/*
* Remap an external interrupt line to the corresponding pin on the
* specified GPIO port.
*
* TODO: This could be rewritten in fewer lines of code.
*/
void exti_select_source(uint32_t exti, uint32_t gpioport)
{
uint32_t line;
for (line = 0; line < 16; line++) {
if (!(exti & (1 << line))) {
continue;
}
uint32_t bits = 0, mask = 0x0F;
switch (gpioport) {
case GPIOA:
bits = 0;
break;
case GPIOB:
bits = 1;
break;
case GPIOC:
bits = 2;
break;
case GPIOD:
bits = 3;
break;
#if defined(GPIOE) && defined(GPIO_PORT_E_BASE)
case GPIOE:
bits = 4;
break;
#endif
#if defined(GPIOF) && defined(GPIO_PORT_F_BASE)
case GPIOF:
bits = 5;
break;
#endif
#if defined(GPIOG) && defined(GPIO_PORT_G_BASE)
case GPIOG:
bits = 6;
break;
#endif
#if defined(GPIOH) && defined(GPIO_PORT_H_BASE)
case GPIOH:
bits = 7;
break;
#endif
#if defined(GPIOI) && defined(GPIO_PORT_I_BASE)
case GPIOI:
bits = 8;
break;
#endif
}
uint8_t shift = (uint8_t)(4 * (line % 4));
uint32_t reg = line / 4;
bits <<= shift;
mask <<= shift;
#if defined(AFIO_BASE)
AFIO_EXTICR(reg) = (AFIO_EXTICR(reg) & ~mask) | bits;
#else
SYSCFG_EXTICR(reg) = (SYSCFG_EXTICR(reg) & ~mask) | bits;
#endif
};
}

View File

@ -0,0 +1,67 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/flash.h>
void flash_set_ws(uint32_t ws)
{
uint32_t reg32;
reg32 = FLASH_ACR;
reg32 &= ~((1 << 0) | (1 << 1) | (1 << 2));
reg32 |= ws;
FLASH_ACR = reg32;
}
void flash_unlock(void)
{
/* Clear the unlock sequence state. */
FLASH_CR |= FLASH_CR_LOCK;
/* Authorize the FPEC access. */
FLASH_KEYR = FLASH_KEYR_KEY1;
FLASH_KEYR = FLASH_KEYR_KEY2;
}
void flash_lock(void)
{
FLASH_CR |= FLASH_CR_LOCK;
}
void flash_clear_pgperr_flag(void)
{
FLASH_SR |= FLASH_SR_PGPERR;
}
void flash_clear_eop_flag(void)
{
FLASH_SR |= FLASH_SR_EOP;
}
void flash_clear_bsy_flag(void)
{
FLASH_SR &= ~FLASH_SR_BSY;
}
void flash_wait_for_last_operation(void)
{
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY);
}

View File

@ -0,0 +1,224 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/flash.h>
static inline void flash_set_program_size(uint32_t psize)
{
FLASH_CR &= ~(((1 << 0) | (1 << 1)) << 8);
FLASH_CR |= psize;
}
void flash_dcache_enable(void)
{
FLASH_ACR |= FLASH_ACR_DCE;
}
void flash_dcache_disable(void)
{
FLASH_ACR &= ~FLASH_ACR_DCE;
}
void flash_icache_enable(void)
{
FLASH_ACR |= FLASH_ACR_ICE;
}
void flash_icache_disable(void)
{
FLASH_ACR &= ~FLASH_ACR_ICE;
}
void flash_prefetch_enable(void)
{
FLASH_ACR |= FLASH_ACR_PRFTEN;
}
void flash_prefetch_disable(void)
{
FLASH_ACR &= ~FLASH_ACR_PRFTEN;
}
void flash_dcache_reset(void)
{
FLASH_ACR |= FLASH_ACR_DCRST;
}
void flash_icache_reset(void)
{
FLASH_ACR |= FLASH_ACR_ICRST;
}
void flash_clear_pgserr_flag(void)
{
FLASH_SR |= FLASH_SR_PGSERR;
}
void flash_clear_pgaerr_flag(void)
{
FLASH_SR |= FLASH_SR_PGAERR;
}
void flash_clear_wrperr_flag(void)
{
FLASH_SR |= FLASH_SR_WRPERR;
}
void flash_clear_status_flags(void)
{
flash_clear_pgserr_flag();
flash_clear_pgaerr_flag();
flash_clear_wrperr_flag();
flash_clear_pgperr_flag();
flash_clear_eop_flag();
flash_clear_bsy_flag();
}
void flash_unlock_option_bytes(void)
{
/* Clear the unlock state. */
FLASH_OPTCR |= FLASH_OPTCR_OPTLOCK;
/* Unlock option bytes. */
FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1;
FLASH_OPTKEYR = FLASH_OPTKEYR_KEY2;
}
void flash_lock_option_bytes(void)
{
FLASH_OPTCR |= FLASH_OPTCR_OPTLOCK;
}
void flash_program_double_word(uint32_t address, uint64_t data)
{
/* Ensure that all flash operations are complete. */
flash_wait_for_last_operation();
flash_set_program_size(FLASH_CR_PROGRAM_X64);
/* Enable writes to flash. */
FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO64(address) = data;
/* Wait for the write to complete. */
flash_wait_for_last_operation();
/* Disable writes to flash. */
FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_word(uint32_t address, uint32_t data)
{
/* Ensure that all flash operations are complete. */
flash_wait_for_last_operation();
flash_set_program_size(FLASH_CR_PROGRAM_X32);
/* Enable writes to flash. */
FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO32(address) = data;
/* Wait for the write to complete. */
flash_wait_for_last_operation();
/* Disable writes to flash. */
FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_half_word(uint32_t address, uint16_t data)
{
flash_wait_for_last_operation();
flash_set_program_size(FLASH_CR_PROGRAM_X16);
FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = data;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_program_byte(uint32_t address, uint8_t data)
{
flash_wait_for_last_operation();
flash_set_program_size(FLASH_CR_PROGRAM_X8);
FLASH_CR |= FLASH_CR_PG;
MMIO8(address) = data;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_program(uint32_t address, uint8_t *data, uint32_t len)
{
/* TODO: Use dword and word size program operations where possible for
* turbo speed.
*/
uint32_t i;
for (i = 0; i < len; i++) {
flash_program_byte(address+i, data[i]);
}
}
void flash_erase_sector(uint8_t sector, uint32_t program_size)
{
flash_wait_for_last_operation();
flash_set_program_size(program_size);
FLASH_CR &= ~(0xF << 3);
FLASH_CR |= (sector << 3) & 0x78;
FLASH_CR |= FLASH_CR_SER;
FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_SER;
FLASH_CR &= ~(0xF << 3);
}
void flash_erase_all_sectors(uint32_t program_size)
{
flash_wait_for_last_operation();
flash_set_program_size(program_size);
FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}
void flash_program_option_bytes(uint32_t data)
{
flash_wait_for_last_operation();
if (FLASH_OPTCR & FLASH_OPTCR_OPTLOCK) {
flash_unlock_option_bytes();
}
FLASH_OPTCR = data & ~0x3;
FLASH_OPTCR |= FLASH_OPTCR_OPTSTRT; /* Enable option byte prog. */
flash_wait_for_last_operation();
}

View File

@ -0,0 +1,151 @@
/** @addtogroup gpio_file
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#define WEAK __attribute__((weak))
#include <libopencm3/stm32/gpio.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief Set a Group of Pins Atomic
Set one or more pins of the given GPIO port to 1 in an atomic operation.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use logical OR '|' to separate
them.
*/
void gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
}
/*---------------------------------------------------------------------------*/
/** @brief Clear a Group of Pins Atomic
Clear one or more pins of the given GPIO port to 0 in an atomic operation.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use logical OR '|' to separate
them.
*/
void gpio_clear(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = (gpios << 16);
}
/*---------------------------------------------------------------------------*/
/** @brief Read a Group of Pins.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be read, use logical OR '|' to separate
them.
@return Unsigned int16 value of the pin values. The bit position of the pin
value returned corresponds to the pin number.
*/
uint16_t gpio_get(uint32_t gpioport, uint16_t gpios)
{
return gpio_port_read(gpioport) & gpios;
}
/*---------------------------------------------------------------------------*/
/** @brief Toggle a Group of Pins
Toggle one or more pins of the given GPIO port. This is not an atomic operation.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use logical OR '|' to separate
them.
*/
void gpio_toggle(uint32_t gpioport, uint16_t gpios)
{
GPIO_ODR(gpioport) ^= gpios;
}
/*---------------------------------------------------------------------------*/
/** @brief Read from a Port
Read the current value of the given GPIO port. Only the lower 16 bits contain
valid pin data.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@return Unsigned int16. The value held in the specified GPIO port.
*/
uint16_t gpio_port_read(uint32_t gpioport)
{
return (uint16_t)GPIO_IDR(gpioport);
}
/*---------------------------------------------------------------------------*/
/** @brief Write to a Port
Write a value to the given GPIO port.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] data Unsigned int16. The value to be written to the GPIO port.
*/
void gpio_port_write(uint32_t gpioport, uint16_t data)
{
GPIO_ODR(gpioport) = data;
}
/*---------------------------------------------------------------------------*/
/** @brief Lock the Configuration of a Group of Pins
The configuration of one or more pins of the given GPIO port is locked. There
is no mechanism to unlock these via software. Unlocking occurs at the next
reset.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be locked, use logical OR '|' to separate
them.
*/
void gpio_port_config_lock(uint32_t gpioport, uint16_t gpios)
{
uint32_t reg32;
/* Special "Lock Key Writing Sequence", see datasheet. */
GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
/* Tell the compiler the variable is actually used. It will get
* optimized out anyways.
*/
reg32 = reg32;
/* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
}
/**@}*/

View File

@ -0,0 +1,206 @@
/** @addtogroup gpio_file
@author @htmlonly &copy; @endhtmlonly 2009
Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
Each I/O port has 16 individually configurable bits. Many I/O pins share GPIO
functionality with a number of alternate functions and must be configured to
the alternate function mode if these are to be accessed. A feature is available
to remap alternative functions to a limited set of alternative pins in the
event of a clash of requirements.
The data registers associated with each port for input and output are 32 bit
with the upper 16 bits unused. The output buffer must be written as a 32 bit
word, but individual bits may be set or reset separately in atomic operations
to avoid race conditions during interrupts. Bits may also be individually
locked to prevent accidental configuration changes. Once locked the
configuration cannot be changed until after the next reset.
Each port bit can be configured as analog or digital input, the latter can be
floating or pulled up or down. As outputs they can be configured as either
push-pull or open drain, digital I/O or alternate function, and with maximum
output speeds of 2MHz, 10MHz, or 50MHz.
On reset all ports are configured as digital floating input.
@section gpio_api_ex Basic GPIO Handling API.
Example 1: Push-pull digital output actions with pullup on ports C2 and C9
@code
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT,
GPIO_PUPD_PULLUP, GPIO2 | GPIO9);
gpio_output_options(GPIOC, GPIO_OTYPE_PP,
GPIO_OSPEED_25MHZ, GPIO2 | GPIO9);
gpio_set(GPIOC, GPIO2 | GPIO9);
gpio_clear(GPIOC, GPIO2);
gpio_toggle(GPIOC, GPIO2 | GPIO9);
gpio_port_write(GPIOC, 0x204);
@endcode
Example 2: Digital input on port C12 with pullup
@code
gpio_mode_setup(GPIOC, GPIO_MODE_INPUT,
GPIO_PUPD_PULLUP, GPIO12);
reg16 = gpio_port_read(GPIOC);
@endcode
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/gpio.h>
/*---------------------------------------------------------------------------*/
/** @brief Set GPIO Pin Mode
Sets the Pin Direction and Analog/Digital Mode, and Output Pin Pullup,
for a set of GPIO pins on a given GPIO port.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] mode Unsigned int8. Pin mode @ref gpio_mode
@param[in] pull_up_down Unsigned int8. Pin pullup/pulldown configuration @ref
gpio_pup
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be set, use bitwise OR '|' to separate
them.
*/
void gpio_mode_setup(uint32_t gpioport, uint8_t mode, uint8_t pull_up_down,
uint16_t gpios)
{
uint16_t i;
uint32_t moder, pupd;
/*
* We want to set the config only for the pins mentioned in gpios,
* but keeping the others, so read out the actual config first.
*/
moder = GPIO_MODER(gpioport);
pupd = GPIO_PUPDR(gpioport);
for (i = 0; i < 16; i++) {
if (!((1 << i) & gpios)) {
continue;
}
moder &= ~GPIO_MODE_MASK(i);
moder |= GPIO_MODE(i, mode);
pupd &= ~GPIO_PUPD_MASK(i);
pupd |= GPIO_PUPD(i, pull_up_down);
}
/* Set mode and pull up/down control registers. */
GPIO_MODER(gpioport) = moder;
GPIO_PUPDR(gpioport) = pupd;
}
/*---------------------------------------------------------------------------*/
/** @brief Set GPIO Output Options
When the pin is set to output mode, this sets the configuration (analog/digital
and open drain/push pull) and speed, for a set of GPIO pins on a given GPIO
port.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] otype Unsigned int8. Pin output type @ref gpio_output_type
@param[in] speed Unsigned int8. Pin speed @ref gpio_speed
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be set, use bitwise OR '|' to separate
them.
*/
void gpio_set_output_options(uint32_t gpioport, uint8_t otype, uint8_t speed,
uint16_t gpios)
{
uint16_t i;
uint32_t ospeedr;
if (otype == 0x1) {
GPIO_OTYPER(gpioport) |= gpios;
} else {
GPIO_OTYPER(gpioport) &= ~gpios;
}
ospeedr = GPIO_OSPEEDR(gpioport);
for (i = 0; i < 16; i++) {
if (!((1 << i) & gpios)) {
continue;
}
ospeedr &= ~GPIO_OSPEED_MASK(i);
ospeedr |= GPIO_OSPEED(i, speed);
}
GPIO_OSPEEDR(gpioport) = ospeedr;
}
/*---------------------------------------------------------------------------*/
/** @brief Set GPIO Alternate Function Selection
Set the alternate function mapping number for each pin. Most pins have
alternate functions associated with them. When set to AF mode, a pin may be
used for one of its allocated alternate functions selected by the number given
here. To determine the number to be used for the desired function refer to the
individual datasheet for the particular device. A table is given under the Pin
Selection chapter.
Note that a number of pins may be set but only with a single AF number. In
practice this would rarely be useful as each pin is likely to require a
different number.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] alt_func_num Unsigned int8. Pin alternate function number @ref
gpio_af_num
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be set, use bitwise OR '|' to separate
them.
*/
void gpio_set_af(uint32_t gpioport, uint8_t alt_func_num, uint16_t gpios)
{
uint16_t i;
uint32_t afrl, afrh;
afrl = GPIO_AFRL(gpioport);
afrh = GPIO_AFRH(gpioport);
for (i = 0; i < 8; i++) {
if (!((1 << i) & gpios)) {
continue;
}
afrl &= ~GPIO_AFR_MASK(i);
afrl |= GPIO_AFR(i, alt_func_num);
}
for (i = 8; i < 16; i++) {
if (!((1 << i) & gpios)) {
continue;
}
afrh &= ~GPIO_AFR_MASK(i - 8);
afrh |= GPIO_AFR(i - 8, alt_func_num);
}
GPIO_AFRL(gpioport) = afrl;
GPIO_AFRH(gpioport) = afrh;
}
/**@}*/

View File

@ -0,0 +1,161 @@
/** @addtogroup hash_file
@author @htmlonly &copy; @endhtmlonly 2013
Mikhail Avkhimenia <mikhail@avkhimenia.net>
This library supports the HASH processor in the STM32F2 and STM32F4
series of ARM Cortex Microcontrollers by ST Microelectronics.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2013 Mikhail Avkhimenia <mikhail@avkhimenia.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/hash.h>
/*---------------------------------------------------------------------------*/
/** @brief HASH Set Mode
Sets up the specified mode - either HASH or HMAC.
@param[in] mode unsigned int8. Hash processor mode: @ref hash_mode
*/
void hash_set_mode(uint8_t mode)
{
HASH_CR &= ~HASH_CR_MODE;
HASH_CR |= mode;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Set Algorithm
Sets up the specified algorithm - either MD5 or SHA1.
@param[in] algorithm unsigned int8. Hash algorithm: @ref hash_algorithm
*/
void hash_set_algorithm(uint8_t algorithm)
{
HASH_CR &= ~HASH_CR_ALGO;
HASH_CR |= algorithm;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Set Data Type
Sets up the specified data type: 32Bit, 16Bit, 8Bit, Bitstring.
@param[in] datatype unsigned int8. Hash data type: @ref hash_data_type
*/
void hash_set_data_type(uint8_t datatype)
{
HASH_CR &= ~HASH_CR_DATATYPE;
HASH_CR |= datatype;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Set Key Length
Sets up the specified key length: Long, Short.
@param[in] keylength unsigned int8. Hash data type: @ref hash_key_length
*/
void hash_set_key_length(uint8_t keylength)
{
HASH_CR &= ~HASH_CR_LKEY;
HASH_CR |= keylength;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Set Last Word Valid Bits
Specifies the number of valid bits in the last word.
@param[in] validbits unsigned int8. Number of valid bits.
*/
void hash_set_last_word_valid_bits(uint8_t validbits)
{
HASH_STR &= ~(HASH_STR_NBW);
HASH_STR |= 32 - validbits;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Init
Initializes the HASH processor.
*/
void hash_init()
{
HASH_CR |= HASH_CR_INIT;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Add data
Puts data into the HASH processor's queue.
@param[in] data unsigned int32. Hash input data.
*/
void hash_add_data(uint32_t data)
{
HASH_DIN = data;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Digest
Starts the processing of the last data block.
*/
void hash_digest()
{
HASH_STR |= HASH_STR_DCAL;
}
/*---------------------------------------------------------------------------*/
/** @brief HASH Get Hash Result
Makes a copy of the resulting hash.
@param[out] data unsigned int32. Hash 4\5 words long depending on the algorithm.
@param[in] algorithm unsigned int8. Hash algorithm: @ref hash_algorithm
*/
void hash_get_result(uint32_t *data)
{
data[0] = HASH_HR[0];
data[1] = HASH_HR[1];
data[2] = HASH_HR[2];
data[3] = HASH_HR[3];
if ((HASH_CR & HASH_CR_ALGO) == HASH_ALGO_SHA1) {
data[4] = HASH_HR[4];
}
}

View File

@ -0,0 +1,412 @@
/** @addtogroup i2c_file
@author @htmlonly &copy; @endhtmlonly 2010
Thomas Otto <tommi@viadmin.org>
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
Devices can have up to two I2C peripherals. The peripherals support SMBus and
PMBus variants.
A peripheral begins after reset in Slave mode. To become a Master a start
condition must be generated. The peripheral will remain in Master mode unless
a multimaster contention is lost or a stop condition is generated.
@todo all sorts of lovely stuff like DMA, Interrupts, SMBus variant, Status
register access, Error conditions
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/stm32/rcc.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief I2C Reset.
The I2C peripheral and all its associated configuration registers are placed in
the reset condition. The reset is effected via the RCC peripheral reset system.
@param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base.
*/
void i2c_reset(uint32_t i2c)
{
switch (i2c) {
case I2C1:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
break;
case I2C2:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Peripheral Enable.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_peripheral_enable(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_PE;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Peripheral Disable.
This must not be reset while in Master mode until a communication has finished.
In Slave mode, the peripheral is disabled only after communication has ended.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_peripheral_disable(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_PE;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send Start Condition.
If in Master mode this will cause a restart condition to occur at the end of the
current transmission. If in Slave mode, this will initiate a start condition
when the current bus activity is completed.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_send_start(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_START;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send Stop Condition.
After the current byte transfer this will initiate a stop condition if in Master
mode, or simply release the bus if in Slave mode.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_send_stop(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_STOP;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Clear Stop Flag.
Clear the "Send Stop" flag in the I2C config register
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_clear_stop(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_STOP;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
This sets an address for Slave mode operation, in 7 bit form.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] slave Unsigned int8. Slave address 0...127.
*/
void i2c_set_own_7bit_slave_address(uint32_t i2c, uint8_t slave)
{
I2C_OAR1(i2c) = (uint16_t)(slave << 1);
I2C_OAR1(i2c) &= ~I2C_OAR1_ADDMODE;
I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set the 10 bit Slave Address for the Peripheral.
This sets an address for Slave mode operation, in 10 bit form.
@todo add "I2C_OAR1(i2c) |= (1 << 14);" as above
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] slave Unsigned int16. Slave address 0...1023.
*/
void i2c_set_own_10bit_slave_address(uint32_t i2c, uint16_t slave)
{
I2C_OAR1(i2c) = (uint16_t)(I2C_OAR1_ADDMODE | slave);
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set Peripheral Clock Frequency.
Set the peripheral clock frequency: 2MHz to 36MHz (the APB frequency). Note
that this is <b> not </b> the I2C bus clock. This is set in conjunction with
the Clock Control register to generate the Master bus clock, see @ref
i2c_set_ccr
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] freq Unsigned int8. Clock Frequency Setting @ref i2c_clock.
*/
void i2c_set_clock_frequency(uint32_t i2c, uint8_t freq)
{
uint16_t reg16;
reg16 = I2C_CR2(i2c) & 0xffc0; /* Clear bits [5:0]. */
reg16 |= freq;
I2C_CR2(i2c) = reg16;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send Data.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] data Unsigned int8. Byte to send.
*/
void i2c_send_data(uint32_t i2c, uint8_t data)
{
I2C_DR(i2c) = data;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set Fast Mode.
Set the clock frequency to the high clock rate mode (up to 400kHz). The actual
clock frequency must be set with @ref i2c_set_clock_frequency
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_set_fast_mode(uint32_t i2c)
{
I2C_CCR(i2c) |= I2C_CCR_FS;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set Standard Mode.
Set the clock frequency to the standard clock rate mode (up to 100kHz). The
actual clock frequency must be set with @ref i2c_set_clock_frequency
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_set_standard_mode(uint32_t i2c)
{
I2C_CCR(i2c) &= ~I2C_CCR_FS;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set Bus Clock Frequency.
Set the bus clock frequency. This is a 12 bit number (0...4095) calculated
from the formulae given in the STM32F1 reference manual in the description
of the CCR field. It is a divisor of the peripheral clock frequency
@ref i2c_set_clock_frequency modified by the fast mode setting
@ref i2c_set_fast_mode
@todo provide additional API assitance to set the clock, eg macros
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] freq Unsigned int16. Bus Clock Frequency Setting 0...4095.
*/
void i2c_set_ccr(uint32_t i2c, uint16_t freq)
{
uint16_t reg16;
reg16 = I2C_CCR(i2c) & 0xf000; /* Clear bits [11:0]. */
reg16 |= freq;
I2C_CCR(i2c) = reg16;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set the Rise Time.
Set the maximum rise time on the bus according to the I2C specification, as 1
more than the specified rise time in peripheral clock cycles. This is a 6 bit
number.
@todo provide additional APIP assistance.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] trise Unsigned int16. Rise Time Setting 0...63.
*/
void i2c_set_trise(uint32_t i2c, uint16_t trise)
{
I2C_TRISE(i2c) = trise;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send the 7-bit Slave Address.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] slave Unsigned int16. Slave address 0...1023.
@param[in] readwrite Unsigned int8. Single bit to instruct slave to receive or
send @ref i2c_rw.
*/
void i2c_send_7bit_address(uint32_t i2c, uint8_t slave, uint8_t readwrite)
{
I2C_DR(i2c) = (uint8_t)((slave << 1) | readwrite);
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Get Data.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
uint8_t i2c_get_data(uint32_t i2c)
{
return I2C_DR(i2c) & 0xff;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Enable Interrupt
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] interrupt Unsigned int32. Interrupt to enable.
*/
void i2c_enable_interrupt(uint32_t i2c, uint32_t interrupt)
{
I2C_CR2(i2c) |= interrupt;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Disable Interrupt
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] interrupt Unsigned int32. Interrupt to disable.
*/
void i2c_disable_interrupt(uint32_t i2c, uint32_t interrupt)
{
I2C_CR2(i2c) &= ~interrupt;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Enable ACK
Enables acking of own 7/10 bit address
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_ack(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_ACK;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Disable ACK
Disables acking of own 7/10 bit address
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_ack(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_ACK;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C NACK Next Byte
Causes the I2C controller to NACK the reception of the next byte
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_nack_next(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_POS;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C NACK Next Byte
Causes the I2C controller to NACK the reception of the current byte
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_nack_current(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_POS;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set clock duty cycle
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] dutycycle Unsigned int32. I2C duty cycle @ref i2c_duty_cycle.
*/
void i2c_set_dutycycle(uint32_t i2c, uint32_t dutycycle)
{
if (dutycycle == I2C_CCR_DUTY_DIV2) {
I2C_CCR(i2c) &= ~I2C_CCR_DUTY;
} else {
I2C_CCR(i2c) |= I2C_CCR_DUTY;
}
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Enable DMA
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_dma(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_DMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Disable DMA
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_dma(uint32_t i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_DMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set DMA last transfer
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_set_dma_last_transfer(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_LAST;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Clear DMA last transfer
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_clear_dma_last_transfer(uint32_t i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_LAST;
}
/**@}*/

View File

@ -0,0 +1,149 @@
/** @addtogroup iwdg_file
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies ksarkies@internode.on.net
This library supports the Independent Watchdog Timer System in the STM32F1xx
series of ARM Cortex Microcontrollers by ST Microelectronics.
The watchdog timer uses the LSI (low speed internal) clock which is low power
and continues to operate during stop and standby modes. Its frequency is
nominally 32kHz (40kHz for the STM32F1xx series) but can vary from as low
as 17kHz up to 60kHz (refer to datasheet electrical characteristics).
Note that the User Configuration option byte provides a means of automatically
enabling the IWDG timer at power on (with counter value 0xFFF). If the
relevant bit is not set, the IWDG timer must be enabled by software.
@note: Tested: CPU STM32F103RET6, Board ET-ARM Stamp STM32
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/iwdg.h>
#define LSI_FREQUENCY 32000
#define COUNT_LENGTH 12
#define COUNT_MASK ((1 << COUNT_LENGTH)-1)
/*---------------------------------------------------------------------------*/
/** @brief IWDG Enable Watchdog Timer
The watchdog timer is started. The timeout period defaults to 512 milliseconds
unless it has been previously defined.
*/
void iwdg_start(void)
{
IWDG_KR = IWDG_KR_START;
}
/*---------------------------------------------------------------------------*/
/** @brief IWDG Set Period in Milliseconds
The countdown period is converted into count and prescale values. The maximum
period is 32.76 seconds; values above this are truncated. Periods less than 1ms
are not supported by this library.
A delay of up to 5 clock cycles of the LSI clock (about 156 microseconds)
can occasionally occur if the prescale or preload registers are currently busy
loading a previous value.
@param[in] period uint32_t Period in milliseconds (< 32760) from a watchdog
reset until a system reset is issued.
*/
void iwdg_set_period_ms(uint32_t period)
{
uint32_t count, prescale, reload, exponent;
/* Set the count to represent ticks of the 32kHz LSI clock */
count = (period << 5);
/* Strip off the first 12 bits to get the prescale value required */
prescale = (count >> 12);
if (prescale > 256) {
exponent = IWDG_PR_DIV256; reload = COUNT_MASK;
} else if (prescale > 128) {
exponent = IWDG_PR_DIV256; reload = (count >> 8);
} else if (prescale > 64) {
exponent = IWDG_PR_DIV128; reload = (count >> 7);
} else if (prescale > 32) {
exponent = IWDG_PR_DIV64; reload = (count >> 6);
} else if (prescale > 16) {
exponent = IWDG_PR_DIV32; reload = (count >> 5);
} else if (prescale > 8) {
exponent = IWDG_PR_DIV16; reload = (count >> 4);
} else if (prescale > 4) {
exponent = IWDG_PR_DIV8; reload = (count >> 3);
} else {
exponent = IWDG_PR_DIV4; reload = (count >> 2);
}
/* Avoid the undefined situation of a zero count */
if (count == 0) {
count = 1;
}
while (iwdg_prescaler_busy());
IWDG_KR = IWDG_KR_UNLOCK;
IWDG_PR = exponent;
while (iwdg_reload_busy());
IWDG_KR = IWDG_KR_UNLOCK;
IWDG_RLR = (reload & COUNT_MASK);
}
/*---------------------------------------------------------------------------*/
/** @brief IWDG Get Reload Register Status
@returns boolean: TRUE if the reload register is busy and unavailable for
loading a new count value.
*/
bool iwdg_reload_busy(void)
{
return IWDG_SR & IWDG_SR_RVU;
}
/*---------------------------------------------------------------------------*/
/** @brief IWDG Get Prescaler Register Status
@returns boolean: TRUE if the prescaler register is busy and unavailable for
loading a new period value.
*/
bool iwdg_prescaler_busy(void)
{
return IWDG_SR & IWDG_SR_PVU;
}
/*---------------------------------------------------------------------------*/
/** @brief IWDG reset Watchdog Timer
The watchdog timer is reset. The counter restarts from the value in the reload
register.
*/
void iwdg_reset(void)
{
IWDG_KR = IWDG_KR_RESET;
}
/**@}*/

View File

@ -0,0 +1,205 @@
/** @addtogroup pwr_file PWR
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/pwr.h>
/*---------------------------------------------------------------------------*/
/** @brief Disable Backup Domain Write Protection.
This allows backup domain registers to be changed. These registers are write
protected after a reset.
*/
void pwr_disable_backup_domain_write_protect(void)
{
PWR_CR |= PWR_CR_DBP;
}
/*---------------------------------------------------------------------------*/
/** @brief Re-enable Backup Domain Write Protection.
This protects backup domain registers from inadvertent change.
*/
void pwr_enable_backup_domain_write_protect(void)
{
PWR_CR &= ~PWR_CR_DBP;
}
/*---------------------------------------------------------------------------*/
/** @brief Enable Power Voltage Detector.
This provides voltage level threshold detection. The result of detection is
provided in the power voltage detector output flag (see @ref pwr_voltage_high)
or by setting the EXTI16 interrupt (see datasheet for configuration details).
@param[in] pvd_level uint32_t. Taken from @ref pwr_pls.
*/
void pwr_enable_power_voltage_detect(uint32_t pvd_level)
{
PWR_CR &= ~PWR_CR_PLS_MASK;
PWR_CR |= (PWR_CR_PVDE | pvd_level);
}
/*---------------------------------------------------------------------------*/
/** @brief Disable Power Voltage Detector.
*/
void pwr_disable_power_voltage_detect(void)
{
PWR_CR &= ~PWR_CR_PVDE;
}
/*---------------------------------------------------------------------------*/
/** @brief Clear the Standby Flag.
This is set when the processor returns from a standby mode.
*/
void pwr_clear_standby_flag(void)
{
PWR_CR |= PWR_CR_CSBF;
}
/*---------------------------------------------------------------------------*/
/** @brief Clear the Wakeup Flag.
This is set when the processor receives a wakeup signal.
*/
void pwr_clear_wakeup_flag(void)
{
PWR_CR |= PWR_CR_CWUF;
}
/*---------------------------------------------------------------------------*/
/** @brief Set Standby Mode in Deep Sleep.
*/
void pwr_set_standby_mode(void)
{
PWR_CR |= PWR_CR_PDDS;
}
/*---------------------------------------------------------------------------*/
/** @brief Set Stop Mode in Deep Sleep.
*/
void pwr_set_stop_mode(void)
{
PWR_CR &= ~PWR_CR_PDDS;
}
/*---------------------------------------------------------------------------*/
/** @brief Voltage Regulator On in Stop Mode.
*/
void pwr_voltage_regulator_on_in_stop(void)
{
PWR_CR &= ~PWR_CR_LPDS;
}
/*---------------------------------------------------------------------------*/
/** @brief Voltage Regulator Low Power in Stop Mode.
*/
void pwr_voltage_regulator_low_power_in_stop(void)
{
PWR_CR |= PWR_CR_LPDS;
}
/*---------------------------------------------------------------------------*/
/** @brief Enable Wakeup Pin.
The wakeup pin is used for waking the processor from standby mode.
*/
void pwr_enable_wakeup_pin(void)
{
PWR_CSR |= PWR_CSR_EWUP;
}
/*---------------------------------------------------------------------------*/
/** @brief Release Wakeup Pin.
The wakeup pin is used for general purpose I/O.
*/
void pwr_disable_wakeup_pin(void)
{
PWR_CSR &= ~PWR_CSR_EWUP;
}
/*---------------------------------------------------------------------------*/
/** @brief Get Voltage Detector Output.
The voltage detector threshold must be set when the power voltage detector is
enabled, see @ref pwr_enable_power_voltage_detect.
@returns boolean: TRUE if the power voltage is above the preset voltage
threshold.
*/
bool pwr_voltage_high(void)
{
return PWR_CSR & PWR_CSR_PVDO;
}
/*---------------------------------------------------------------------------*/
/** @brief Get Standby Flag.
The standby flag is set when the processor returns from a standby state. It is
cleared by software (see @ref pwr_clear_standby_flag).
@returns boolean: TRUE if the processor was in standby state.
*/
bool pwr_get_standby_flag(void)
{
return PWR_CSR & PWR_CSR_SBF;
}
/*---------------------------------------------------------------------------*/
/** @brief Get Wakeup Flag.
The wakeup flag is set when a wakeup event has been received. It is
cleared by software (see @ref pwr_clear_wakeup_flag).
@returns boolean: TRUE if a wakeup event was received.
*/
bool pwr_get_wakeup_flag(void)
{
return PWR_CSR & PWR_CSR_WUF;
}
/**@}*/

View File

@ -0,0 +1,123 @@
/** @addtogroup rtc_file
@author @htmlonly &copy; @endhtmlonly 2012 Karl Palsson <karlp@tweak.net.au>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/rtc.h>
/*---------------------------------------------------------------------------*/
/** @brief Set RTC prescalars.
This sets the RTC synchronous and asynchronous prescalars.
*/
void rtc_set_prescaler(uint32_t sync, uint32_t async)
{
/*
* Even if only one of the two fields needs to be changed,
* 2 separate write accesses must be performed to the RTC_PRER register.
*/
RTC_PRER = (sync & RTC_PRER_PREDIV_S_MASK);
RTC_PRER |= (async << RTC_PRER_PREDIV_A_SHIFT);
}
/*---------------------------------------------------------------------------*/
/** @brief Wait for RTC registers to be synchronised with the APB1 bus
Time and Date are accessed through shadow registers which must be synchronized
*/
void rtc_wait_for_synchro(void)
{
/* Unlock RTC registers */
RTC_WPR = 0xca;
RTC_WPR = 0x53;
RTC_ISR &= ~(RTC_ISR_RSF);
while (!(RTC_ISR & RTC_ISR_RSF));
/* disable write protection again */
RTC_WPR = 0xff;
}
/*---------------------------------------------------------------------------*/
/** @brief Unlock write access to the RTC registers
*/
void rtc_unlock(void)
{
RTC_WPR = 0xca;
RTC_WPR = 0x53;
}
/*---------------------------------------------------------------------------*/
/** @brief Lock write access to the RTC registers
*/
void rtc_lock(void)
{
RTC_WPR = 0xff;
}
/*---------------------------------------------------------------------------*/
/** @brief Sets the wakeup time auto-reload value
*/
void rtc_set_wakeup_time(uint16_t wkup_time, uint8_t rtc_cr_wucksel)
{
/* FTFM:
* The following sequence is required to configure or change the wakeup
* timer auto-reload value (WUT[15:0] in RTC_WUTR):
* 1. Clear WUTE in RTC_CR to disable the wakeup timer.
*/
RTC_CR &= ~RTC_CR_WUTE;
/* 2. Poll WUTWF until it is set in RTC_ISR to make sure the access to
* wakeup auto-reload counter and to WUCKSEL[2:0] bits is allowed.
* It takes around 2 RTCCLK clock cycles (due to clock
* synchronization).
*/
while (!((RTC_ISR) & (RTC_ISR_WUTWF)));
/* 3. Program the wakeup auto-reload value WUT[15:0], and the wakeup
* clock selection (WUCKSEL[2:0] bits in RTC_CR).Set WUTE in RTC_CR
* to enable the timer again. The wakeup timer restarts
* down-counting.
*/
RTC_WUTR = wkup_time;
RTC_CR |= (rtc_cr_wucksel << RTC_CR_WUCLKSEL_SHIFT);
RTC_CR |= RTC_CR_WUTE;
}
/*---------------------------------------------------------------------------*/
/** @brief Clears the wakeup flag
@details This function should be called first in the rtc_wkup_isr()
*/
void rtc_clear_wakeup_flag(void)
{
RTC_ISR &= ~RTC_ISR_WUTF;
}
/**@}*/

View File

@ -0,0 +1,698 @@
/** @addtogroup spi_file
@author @htmlonly &copy; @endhtmlonly 2009
Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
Devices can have up to three SPI peripherals. The common 4-wire full-duplex
mode of operation is supported, along with 3-wire variants using unidirectional
communication modes or half-duplex bidirectional communication. A variety of
options allows many of the SPI variants to be supported. Multimaster operation
is also supported. A CRC can be generated and checked in hardware.
@note Some JTAG pins need to be remapped if SPI is to be used.
@note The I2S protocol shares the SPI hardware so the two protocols cannot be
used at the same time on the same peripheral.
Example: 1Mbps, positive clock polarity, leading edge trigger, 8-bit words,
LSB first.
@code
spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
SPI_CR1_LSBFIRST);
spi_write(SPI1, 0x55); // 8-bit write
spi_write(SPI1, 0xaa88); // 16-bit write
reg8 = spi_read(SPI1); // 8-bit read
reg16 = spi_read(SPI1); // 16-bit read
@endcode
@todo need additional functions to aid ISRs in retrieving status
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/rcc.h>
/*
* SPI and I2S code.
*
* Examples:
* spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
* SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
* SPI_CR1_LSBFIRST);
* spi_write(SPI1, 0x55); // 8-bit write
* spi_write(SPI1, 0xaa88); // 16-bit write
* reg8 = spi_read(SPI1); // 8-bit read
* reg16 = spi_read(SPI1); // 16-bit read
*/
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief SPI Reset.
The SPI peripheral and all its associated configuration registers are placed in
the reset condition. The reset is effected via the RCC peripheral reset system.
@param[in] spi_peripheral Unsigned int32. SPI peripheral identifier @ref
spi_reg_base.
*/
void spi_reset(uint32_t spi_peripheral)
{
/* there is another way of resetting mechanism on F0. It will be extended to all
families of stm32 and this function will be deprecated and deleted in the
future.*/
#if !defined(STM32F0)
switch (spi_peripheral) {
case SPI1:
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_SPI1RST);
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_SPI1RST);
break;
case SPI2:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
break;
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F3) || defined(STM32F4)
case SPI3:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
break;
#endif
}
#endif
}
/* TODO: Error handling? */
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable.
The SPI peripheral is enabled.
@todo Error handling?
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_SPE; /* Enable SPI. */
}
/* TODO: Error handling? */
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable.
The SPI peripheral is disabled.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable(uint32_t spi)
{
uint32_t reg32;
reg32 = SPI_CR1(spi);
reg32 &= ~(SPI_CR1_SPE); /* Disable SPI. */
SPI_CR1(spi) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Clean Disable.
Disable the SPI peripheral according to the procedure in section 23.3.8 of the
reference manual. This prevents corruption of any ongoing transfers and
prevents the BSY flag from becoming unreliable.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@returns data Unsigned int16. 8 or 16 bit data from final read.
*/
uint16_t spi_clean_disable(uint32_t spi)
{
/* Wait to receive last data */
while (!(SPI_SR(spi) & SPI_SR_RXNE));
uint16_t data = SPI_DR(spi);
/* Wait to transmit last data */
while (!(SPI_SR(spi) & SPI_SR_TXE));
/* Wait until not busy */
while (SPI_SR(spi) & SPI_SR_BSY);
SPI_CR1(spi) &= ~SPI_CR1_SPE;
return data;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Data Write.
Data is written to the SPI interface.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
*/
void spi_write(uint32_t spi, uint16_t data)
{
/* Write data (8 or 16 bits, depending on DFF) into DR. */
SPI_DR(spi) = data;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Data Write with Blocking.
Data is written to the SPI interface after the previous write transfer has
finished.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
*/
void spi_send(uint32_t spi, uint16_t data)
{
/* Wait for transfer finished. */
while (!(SPI_SR(spi) & SPI_SR_TXE));
/* Write data (8 or 16 bits, depending on DFF) into DR. */
SPI_DR(spi) = data;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Data Read.
Data is read from the SPI interface after the incoming transfer has finished.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@returns data Unsigned int16. 8 or 16 bit data.
*/
uint16_t spi_read(uint32_t spi)
{
/* Wait for transfer finished. */
while (!(SPI_SR(spi) & SPI_SR_RXNE));
/* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
return SPI_DR(spi);
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Data Write and Read Exchange.
Data is written to the SPI interface, then a read is done after the incoming
transfer has finished.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
@returns data Unsigned int16. 8 or 16 bit data.
*/
uint16_t spi_xfer(uint32_t spi, uint16_t data)
{
spi_write(spi, data);
/* Wait for transfer finished. */
while (!(SPI_SR(spi) & SPI_SR_RXNE));
/* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
return SPI_DR(spi);
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Bidirectional Simplex Mode.
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
(using a clock wire and a bidirectional data wire).
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_bidirectional_mode(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Unidirectional Mode.
The SPI peripheral is set for unidirectional transfers. This is used in full
duplex mode or when the SPI is placed in two-wire simplex mode that uses a
clock wire and a unidirectional data wire.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_unidirectional_mode(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_BIDIMODE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
(using a clock wire and a bidirectional data wire), and is placed in a receive
state.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_bidirectional_receive_only_mode(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
SPI_CR1(spi) &= ~SPI_CR1_BIDIOE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
(using a clock wire and a bidirectional data wire), and is placed in a transmit
state.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_bidirectional_transmit_only_mode(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
SPI_CR1(spi) |= SPI_CR1_BIDIOE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable the CRC.
The SPI peripheral is set to use a CRC field for transmit and receive.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_crc(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_CRCEN;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable the CRC.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_crc(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CRCEN;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Next Transmit is a Data Word
The next transmission to take place is a data word from the transmit buffer.
This must be called before transmission to distinguish between sending
of a data or CRC word.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_next_tx_from_buffer(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CRCNEXT;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Next Transmit is a CRC Word
The next transmission to take place is a crc word from the hardware crc unit.
This must be called before transmission to distinguish between sending
of a data or CRC word.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_next_tx_from_crc(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_CRCNEXT;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Full Duplex (3-wire) Mode
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_full_duplex_mode(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_RXONLY;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Receive Only Mode for Simplex (2-wire) Unidirectional
Transfers
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_receive_only_mode(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_RXONLY;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable Slave Management by Hardware
In slave mode the NSS hardware input is used as a select enable for the slave.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_software_slave_management(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_SSM;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable Slave Management by Software
In slave mode the NSS hardware input is replaced by an internal software
enable/disable of the slave (@ref spi_set_nss_high).
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_software_slave_management(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_SSM;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Software NSS Signal High
In slave mode, and only when software slave management is used, this replaces
the NSS signal with a slave select enable signal.
@todo these should perhaps be combined with an SSM enable as it is meaningless
otherwise
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_nss_high(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_SSI;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Software NSS Signal Low
In slave mode, and only when software slave management is used, this replaces
the NSS signal with a slave select disable signal.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_nss_low(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_SSI;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set to Send LSB First
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_send_lsb_first(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_LSBFIRST;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set to Send MSB First
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_send_msb_first(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_LSBFIRST;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Baudrate Prescaler
@todo Why is this specification different to the spi_init_master baudrate
values?
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] baudrate Unsigned int8. Baudrate prescale value @ref spi_br_pre.
*/
void spi_set_baudrate_prescaler(uint32_t spi, uint8_t baudrate)
{
uint32_t reg32;
if (baudrate > 7) {
return;
}
reg32 = (SPI_CR1(spi) & 0xffc7); /* Clear bits [5:3]. */
reg32 |= (baudrate << 3);
SPI_CR1(spi) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set to Master Mode
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_master_mode(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_MSTR;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set to Slave Mode
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_slave_mode(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_MSTR;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Polarity to High when Idle
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_polarity_1(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_CPOL;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Polarity to Low when Idle
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_polarity_0(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CPOL;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Phase to Capture on Trailing Edge
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_phase_1(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_CPHA;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Phase to Capture on Leading Edge
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_phase_0(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CPHA;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable the Transmit Buffer Empty Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_tx_buffer_empty_interrupt(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable the Transmit Buffer Empty Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_tx_buffer_empty_interrupt(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable the Receive Buffer Ready Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_rx_buffer_not_empty_interrupt(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_RXNEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable the Receive Buffer Ready Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_rx_buffer_not_empty_interrupt(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_RXNEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable the Error Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_error_interrupt(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_ERRIE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable the Error Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_error_interrupt(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_ERRIE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the NSS Pin as an Output
Normally used in master mode to allows the master to place all devices on the
SPI bus into slave mode. Multimaster mode is not possible.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_ss_output(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_SSOE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set the NSS Pin as an Input
In master mode this allows the master to sense the presence of other masters. If
NSS is then pulled low the master is placed into slave mode. In slave mode NSS
becomes a slave enable.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_ss_output(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_SSOE;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable Transmit Transfers via DMA
This allows transmissions to proceed unattended using DMA to move data to the
transmit buffer as it becomes available. The DMA channels provided for each
SPI peripheral are given in the Technical Manual DMA section.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_tx_dma(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_TXDMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable Transmit Transfers via DMA
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_tx_dma(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_TXDMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Enable Receive Transfers via DMA
This allows received data streams to proceed unattended using DMA to move data
from the receive buffer as data becomes available. The DMA channels provided
for each SPI peripheral are given in the Technical Manual DMA section.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_rx_dma(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_RXDMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Disable Receive Transfers via DMA
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_rx_dma(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_RXDMAEN;
}
/**@}*/

View File

@ -0,0 +1,137 @@
/** @addtogroup spi_file
@author @htmlonly &copy; @endhtmlonly 2009
Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
Devices can have up to three SPI peripherals. The common 4-wire full-duplex
mode of operation is supported, along with 3-wire variants using unidirectional
communication modes or half-duplex bidirectional communication. A variety of
options allows many of the SPI variants to be supported. Multimaster operation
is also supported. A CRC can be generated and checked in hardware.
@note Some JTAG pins need to be remapped if SPI is to be used.
@note The I2S protocol shares the SPI hardware so the two protocols cannot be
used at the same time on the same peripheral.
Example: 1Mbps, positive clock polarity, leading edge trigger, 8-bit words,
LSB first.
@code
spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
SPI_CR1_LSBFIRST);
spi_write(SPI1, 0x55); // 8-bit write
spi_write(SPI1, 0xaa88); // 16-bit write
reg8 = spi_read(SPI1); // 8-bit read
reg16 = spi_read(SPI1); // 16-bit read
@endcode
@todo need additional functions to aid ISRs in retrieving status
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/rcc.h>
/*
* SPI and I2S code.
*
* Examples:
* spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
* SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
* SPI_CR1_LSBFIRST);
* spi_write(SPI1, 0x55); // 8-bit write
* spi_write(SPI1, 0xaa88); // 16-bit write
* reg8 = spi_read(SPI1); // 8-bit read
* reg16 = spi_read(SPI1); // 16-bit read
*/
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief Configure the SPI as Master.
The SPI peripheral is configured as a master with communication parameters
baudrate, data format 8/16 bits, frame format lsb/msb first, clock polarity
and phase. The SPI enable, CRC enable and CRC next controls are not affected.
These must be controlled separately.
@todo NSS pin handling.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] br Unsigned int32. Baudrate @ref spi_baudrate.
@param[in] cpol Unsigned int32. Clock polarity @ref spi_cpol.
@param[in] cpha Unsigned int32. Clock Phase @ref spi_cpha.
@param[in] dff Unsigned int32. Data frame format 8/16 bits @ref spi_dff.
@param[in] lsbfirst Unsigned int32. Frame format lsb/msb first @ref
spi_lsbfirst.
@returns int. Error code.
*/
int spi_init_master(uint32_t spi, uint32_t br, uint32_t cpol, uint32_t cpha,
uint32_t dff, uint32_t lsbfirst)
{
uint32_t reg32 = SPI_CR1(spi);
/* Reset all bits omitting SPE, CRCEN and CRCNEXT bits. */
reg32 &= SPI_CR1_SPE | SPI_CR1_CRCEN | SPI_CR1_CRCNEXT;
reg32 |= SPI_CR1_MSTR; /* Configure SPI as master. */
reg32 |= br; /* Set baud rate bits. */
reg32 |= cpol; /* Set CPOL value. */
reg32 |= cpha; /* Set CPHA value. */
reg32 |= dff; /* Set data format (8 or 16 bits). */
reg32 |= lsbfirst; /* Set frame format (LSB- or MSB-first). */
/* TODO: NSS pin handling. */
SPI_CR1(spi) = reg32;
return 0; /* TODO */
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Data Frame Format to 8 bits
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_dff_8bit(uint32_t spi)
{
SPI_CR1(spi) &= ~SPI_CR1_DFF;
}
/*---------------------------------------------------------------------------*/
/** @brief SPI Set Data Frame Format to 16 bits
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_dff_16bit(uint32_t spi)
{
SPI_CR1(spi) |= SPI_CR1_DFF;
}
/**@}*/

View File

@ -0,0 +1,58 @@
/** @addtogroup timer_file
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/timer.h>
/*---------------------------------------------------------------------------*/
/** @brief Set Input Polarity
The timer channel must be set to input capture mode.
@param[in] timer_peripheral Unsigned int32. Timer register address base
@param[in] ic ::tim_ic_id. Input Capture channel designator.
@param[in] pol ::tim_ic_pol. Input Capture polarity control.
*/
void timer_ic_set_polarity(uint32_t timer_peripheral, enum tim_ic_id ic,
enum tim_ic_pol pol)
{
/* Clear CCxP and CCxNP to zero. For both edge trigger both fields are
* set. Case 10 is invalid.
*/
TIM_CCER(timer_peripheral) &= ~(0x6 << (ic * 4));
switch (pol) {
case TIM_IC_RISING: /* 00 */
break;
case TIM_IC_BOTH: /* 11 */
TIM_CCER(timer_peripheral) |= (0x6 << (ic * 4));
break;
case TIM_IC_FALLING: /* 01 */
TIM_CCER(timer_peripheral) |= (0x2 << (ic * 4));
}
}
/**@}*/

View File

@ -0,0 +1,53 @@
/** @addtogroup timer_file
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/timer.h>
/*---------------------------------------------------------------------------*/
/** @brief Set Timer Option
Set timer options register on TIM2 or TIM5, used for trigger remapping on TIM2,
and similarly for TIM5 for oscillator calibration purposes.
@param[in] timer_peripheral Unsigned int32. Timer register address base
@returns Unsigned int32. Option flags TIM2: @ref tim2_opt_trigger_remap, TIM5:
@ref tim5_opt_trigger_remap.
*/
void timer_set_option(uint32_t timer_peripheral, uint32_t option)
{
if (timer_peripheral == TIM2) {
TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
} else if (timer_peripheral == TIM5) {
TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
}
}
/**@}*/

View File

@ -0,0 +1,367 @@
/** @addtogroup usart_file
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
This library supports the USART/UART in the STM32F series
of ARM Cortex Microcontrollers by ST Microelectronics.
Devices can have up to 3 USARTs and 2 UARTs.
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/rcc.h>
/*---------------------------------------------------------------------------*/
/** @brief USART Set Baudrate.
The baud rate is computed from the APB high-speed prescaler clock (for
USART1/6) or the APB low-speed prescaler clock (for other USARTs). These values
must be correctly set before calling this function (refer to the
rcc_clock_setup-* functions in RCC).
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] baud unsigned 32 bit. Baud rate specified in Hz.
*/
void usart_set_baudrate(uint32_t usart, uint32_t baud)
{
uint32_t clock = rcc_ppre1_frequency;
#if defined STM32F2 || defined STM32F4
if ((usart == USART1) ||
(usart == USART6)) {
clock = rcc_ppre2_frequency;
}
#else
if (usart == USART1) {
clock = rcc_ppre2_frequency;
}
#endif
/*
* Yes it is as simple as that. The reference manual is
* talking about fractional calculation but it seems to be only
* marketting babble to sound awesome. It is nothing else but a
* simple divider to generate the correct baudrate.
*
* Note: We round() the value rather than floor()ing it, for more
* accurate divisor selection.
*/
USART_BRR(usart) = ((2 * clock) + baud) / (2 * baud);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Word Length.
The word length is set to 8 or 9 bits. Note that the last bit will be a parity
bit if parity is enabled, in which case the data length will be 7 or 8 bits
respectively.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] bits unsigned 32 bit. Word length in bits 8 or 9.
*/
void usart_set_databits(uint32_t usart, uint32_t bits)
{
if (bits == 8) {
USART_CR1(usart) &= ~USART_CR1_M; /* 8 data bits */
} else {
USART_CR1(usart) |= USART_CR1_M; /* 9 data bits */
}
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Stop Bit(s).
The stop bits are specified as 0.5, 1, 1.5 or 2.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] stopbits unsigned 32 bit. Stop bits @ref usart_cr2_stopbits.
*/
void usart_set_stopbits(uint32_t usart, uint32_t stopbits)
{
uint32_t reg32;
reg32 = USART_CR2(usart);
reg32 = (reg32 & ~USART_CR2_STOPBITS_MASK) | stopbits;
USART_CR2(usart) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Parity.
The parity bit can be selected as none, even or odd.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] parity unsigned 32 bit. Parity @ref usart_cr1_parity.
*/
void usart_set_parity(uint32_t usart, uint32_t parity)
{
uint32_t reg32;
reg32 = USART_CR1(usart);
reg32 = (reg32 & ~USART_PARITY_MASK) | parity;
USART_CR1(usart) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Rx/Tx Mode.
The mode can be selected as Rx only, Tx only or Rx+Tx.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] mode unsigned 32 bit. Mode @ref usart_cr1_mode.
*/
void usart_set_mode(uint32_t usart, uint32_t mode)
{
uint32_t reg32;
reg32 = USART_CR1(usart);
reg32 = (reg32 & ~USART_MODE_MASK) | mode;
USART_CR1(usart) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Hardware Flow Control.
The flow control bit can be selected as none, RTS, CTS or RTS+CTS.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] flowcontrol unsigned 32 bit. Flowcontrol @ref usart_cr3_flowcontrol.
*/
void usart_set_flow_control(uint32_t usart, uint32_t flowcontrol)
{
uint32_t reg32;
reg32 = USART_CR3(usart);
reg32 = (reg32 & ~USART_FLOWCONTROL_MASK) | flowcontrol;
USART_CR3(usart) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable(uint32_t usart)
{
USART_CR1(usart) |= USART_CR1_UE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Disable.
At the end of the current frame, the USART is disabled to reduce power.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_disable(uint32_t usart)
{
USART_CR1(usart) &= ~USART_CR1_UE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Send Data Word with Blocking
Blocks until the transmit data buffer becomes empty then writes the next data
word for transmission.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] data unsigned 16 bit.
*/
void usart_send_blocking(uint32_t usart, uint16_t data)
{
usart_wait_send_ready(usart);
usart_send(usart, data);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word with Blocking.
Wait until a data word has been received then return the word.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@returns unsigned 16 bit data word.
*/
uint16_t usart_recv_blocking(uint32_t usart)
{
usart_wait_recv_ready(usart);
return usart_recv(usart);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver DMA Enable.
DMA is available on:
@li USART1 Rx DMA1 channel 5.
@li USART2 Rx DMA1 channel 6.
@li USART3 Rx DMA1 channel 3.
@li UART4 Rx DMA2 channel 3.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable_rx_dma(uint32_t usart)
{
USART_CR3(usart) |= USART_CR3_DMAR;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver DMA Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_disable_rx_dma(uint32_t usart)
{
USART_CR3(usart) &= ~USART_CR3_DMAR;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter DMA Enable.
DMA is available on:
@li USART1 Tx DMA1 channel 4.
@li USART2 Tx DMA1 channel 7.
@li USART3 Tx DMA1 channel 2.
@li UART4 Tx DMA2 channel 5.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable_tx_dma(uint32_t usart)
{
USART_CR3(usart) |= USART_CR3_DMAT;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter DMA Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_disable_tx_dma(uint32_t usart)
{
USART_CR3(usart) &= ~USART_CR3_DMAT;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver Interrupt Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable_rx_interrupt(uint32_t usart)
{
USART_CR1(usart) |= USART_CR1_RXNEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver Interrupt Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_disable_rx_interrupt(uint32_t usart)
{
USART_CR1(usart) &= ~USART_CR1_RXNEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter Interrupt Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable_tx_interrupt(uint32_t usart)
{
USART_CR1(usart) |= USART_CR1_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter Interrupt Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_disable_tx_interrupt(uint32_t usart)
{
USART_CR1(usart) &= ~USART_CR1_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Error Interrupt Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable_error_interrupt(uint32_t usart)
{
USART_CR3(usart) |= USART_CR3_EIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Error Interrupt Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_disable_error_interrupt(uint32_t usart)
{
USART_CR3(usart) &= ~USART_CR3_EIE;
}
/**@}*/

View File

@ -0,0 +1,143 @@
/** @addtogroup usart_file
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
This library supports the USART/UART in the STM32F series
of ARM Cortex Microcontrollers by ST Microelectronics.
Devices can have up to 3 USARTs and 2 UARTs.
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/rcc.h>
/*---------------------------------------------------------------------------*/
/** @brief USART Send a Data Word.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] data unsigned 16 bit.
*/
void usart_send(uint32_t usart, uint16_t data)
{
/* Send data. */
USART_DR(usart) = (data & USART_DR_MASK);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word.
If parity is enabled the MSB (bit 7 or 8 depending on the word length) is the
parity bit.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@returns unsigned 16 bit data word.
*/
uint16_t usart_recv(uint32_t usart)
{
/* Receive data. */
return USART_DR(usart) & USART_DR_MASK;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Wait for Transmit Data Buffer Empty
Blocks until the transmit data buffer becomes empty and is ready to accept the
next data word.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_wait_send_ready(uint32_t usart)
{
/* Wait until the data has been transferred into the shift register. */
while ((USART_SR(usart) & USART_SR_TXE) == 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Wait for Received Data Available
Blocks until the receive data buffer holds a valid received data word.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_wait_recv_ready(uint32_t usart)
{
/* Wait until the data is ready to be received. */
while ((USART_SR(usart) & USART_SR_RXNE) == 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Status Flag.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
@returns boolean: flag set.
*/
bool usart_get_flag(uint32_t usart, uint32_t flag)
{
return ((USART_SR(usart) & flag) != 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Return Interrupt Source.
Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was
set and the interrupt was enabled. If the specified flag is not an interrupt
flag, the function returns false.
@todo These are the most important interrupts likely to be used. Others
relating to LIN break, and error conditions in multibuffer communication, need
to be added for completeness.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
@returns boolean: flag and interrupt enable both set.
*/
bool usart_get_interrupt_source(uint32_t usart, uint32_t flag)
{
uint32_t flag_set = (USART_SR(usart) & flag);
/* IDLE, RXNE, TC, TXE interrupts */
if ((flag >= USART_SR_IDLE) && (flag <= USART_SR_TXE)) {
return ((flag_set & USART_CR1(usart)) != 0);
/* Overrun error */
} else if (flag == USART_SR_ORE) {
return flag_set && (USART_CR3(usart) & USART_CR3_CTSIE);
}
return false;
}
/**@}*/

View File

@ -0,0 +1,60 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@ŧweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/desig.h>
uint16_t desig_get_flash_size(void)
{
return DESIG_FLASH_SIZE;
}
void desig_get_unique_id(uint32_t result[])
{
/* Could also just return a pointer to the start? read it as they wish?
*/
uint16_t bits15_0 = DESIG_UID_15_0;
uint32_t bits31_16 = DESIG_UID_31_16;
uint32_t bits63_32 = DESIG_UID_63_32;
uint32_t bits95_64 = DESIG_UID_95_64;
result[0] = bits95_64;
result[1] = bits63_32;
result[2] = bits31_16 << 16 | bits15_0;
}
void desig_get_unique_id_as_string(char *string,
unsigned int string_len)
{
int i, len;
uint8_t device_id[12];
static const char chars[] = "0123456789ABCDEF";
desig_get_unique_id((uint32_t *)device_id);
/* Each byte produces two characters */
len = (2 * sizeof(device_id) < string_len) ?
2 * sizeof(device_id) : string_len - 1;
for (i = 0; i < len; i += 2) {
string[i] = chars[(device_id[i / 2] >> 0) & 0x0F];
string[i + 1] = chars[(device_id[i / 2] >> 4) & 0x0F];
}
string[len] = '\0';
}

View File

@ -0,0 +1,46 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32f0
PREFIX ?= arm-none-eabi
#PREFIX ?= arm-elf
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g \
-Wall -Wextra -Wimplicit-function-declaration \
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wshadow \
-I../../../include -fno-common \
-mcpu=cortex-m0 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F0
ARFLAGS = rcs
OBJS = flash.o rcc.o usart.o dma.o rtc.o comparator.o spi.o crc.o \
dac.o i2c.o iwdg.o pwr.o gpio.o timer.o adc.o
OBJS += gpio_common_all.o gpio_common_f0234.o crc_common_all.o \
pwr_common_all.o iwdg_common_all.o rtc_common_l1f024.o \
dma_common_l1f013.o exti_common_all.o spi_common_all.o
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include

View File

@ -0,0 +1,835 @@
/** @defgroup adc_file ADC
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx Analog to Digital Converters</b>
*
* based on F3 file
*
* @date 14 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/cm3/assert.h>
#include <libopencm3/stm32/adc.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_opmode ADC Operation mode API
* @ingroup adc_file
*
* @brief ADC Result API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Continuous Conversion Mode
*
* In this mode the ADC starts a new conversion of a single channel or a channel
* group immediately following completion of the previous channel group
* conversion.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_set_continuous_conversion_mode(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_CONT;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Single Conversion Mode
*
* In this mode the ADC performs a conversion of one channel or a channel group
* and stops.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_set_single_conversion_mode(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_CONT;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Discontinuous Mode for Regular Conversions
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_discontinuous_mode(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_DISCEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Discontinuous Mode for Regular Conversions
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_discontinuous_mode(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_DISCEN;
}
/*---------------------------------------------------------------------------*/
/** ADC Set operation mode
*
* There are some operation modes, common for entire stm32 branch. In the text
* the braces are describing result to single trigger event. The trigger event
* is described by character T in the description. The ADC is configured to
* convert list of inputs [0, 1, 2, 3]. In Grouped modes, there is used group
* size of 2 conversions in the examples
*
* @li @c ADC_MODE_SEQUENTIAL: T(0) T(1) T(2) T(3)[EOSEQ] T(0) T(1) T(2) ...
*
* In this mode, after the trigger event a single channel is converted and the
* next channel in the list is prepared to convert on next trigger edge.
*
* @note This mode can be emulated by ADC_MODE_GROUPED with group size
* of 1. @par
*
* @li @c ADC_MODE_SCAN: T(0123)[EOSEQ] T(0123)[EOSEQ] T(0123)[EOSEQ]
*
* In this mode, after the trigger event, all channels will be converted once,
* storing results sequentially.
*
* @note The DMA must be configured properly for more than single channel to
* convert. @par
*
* @li @c ADC_MODE_SCAN_INFINITE: T(0123[EOSEQ]0123[EOSEQ]0123[EOSEQ]...)
*
* In this mode, after the trigger event, all channels from the list are
* converted. At the end of list, the conversion continues from the beginning.
*
* @note The DMA must be configured properly to operate in this mode.@par
*
* @li @c ADC_MODE_GROUPED: T(12) T(34)[EOSEQ] T(12) T(34)[EOSEQ] T(12)
*
* In this mode, after the trigger event, a specified group size of channels
* are converted. If the end of channel list occurs, the EOSEQ is generated
* and on the next trigger it wraps to the beginning.
*
* @note The DMA must be configured properly to operate on more than single
* channel conversion groups.@par
*
* @warning not all families supports all modes of operation of ADC.
*
* @par
*
*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Set conversion operation mode
*
* @note on SEQUENTIAL mode, the trigger event is neccesary to start conversion.
* @par
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] adc ::adc_opmode. ADC operation mode (@ref adc_opmode)
*/
void adc_set_operation_mode(uint32_t adc, enum adc_opmode opmode)
{
switch (opmode) {
case ADC_MODE_SEQUENTIAL:
ADC_CFGR1(adc) &= ~ADC_CFGR1_CONT;
ADC_CFGR1(adc) |= ADC_CFGR1_DISCEN;
break;
case ADC_MODE_SCAN:
ADC_CFGR1(adc) &= ~(ADC_CFGR1_CONT | ADC_CFGR1_DISCEN);
break;
case ADC_MODE_SCAN_INFINITE:
ADC_CFGR1(adc) &= ~ADC_CFGR1_DISCEN;
ADC_CFGR1(adc) |= ADC_CFGR1_CONT;
break;
}
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_result ADC Result API
* @ingroup adc_file
*
* @brief ADC Result API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Software Triggered Conversion on Regular Channels
*
* This starts conversion on a set of defined regular channels. It is cleared
* by hardware once conversion starts.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_start_conversion_regular(uint32_t adc)
{
/* Start conversion on regular channels. */
ADC_CR(adc) |= ADC_CR_ADSTART;
/* Wait until the ADC starts the conversion. */
while (ADC_CR(adc) & ADC_CR_ADSTART);
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Read the End-of-Conversion Flag
*
* This flag is set after all channels of a regular or injected group have been
* converted.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @returns bool. End of conversion flag.
*/
bool adc_eoc(uint32_t adc)
{
return ((ADC_ISR(adc) & ADC_ISR_EOC) != 0);
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Read from the Regular Conversion Result Register
*
* The result read back is 12 bits, right or left aligned within the first
* 16 bits. For ADC1 only, the higher 16 bits will hold the result from ADC2 if
* an appropriate dual mode has been set @see adc_set_dual_mode.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @returns Unsigned int32 conversion result.
*/
uint32_t adc_read_regular(uint32_t adc)
{
return ADC_DR(adc);
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_trigger ADC Trigger API
* @ingroup adc_file
*
* @brief ADC Trigger API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable an External Trigger for Regular Channels
*
* This enables an external trigger for set of defined regular channels, and
* sets the polarity of the trigger event: rising or falling edge or both. Note
* that if the trigger polarity is zero, triggering is disabled.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] trigger Unsigned int32. Trigger identifier
* @ref adc_trigger_regular
* @param[in] polarity Unsigned int32. Trigger polarity @ref
* adc_trigger_polarity_regular
*/
void adc_enable_external_trigger_regular(uint32_t adc, uint32_t trigger,
uint32_t polarity)
{
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_EXTSEL) | trigger;
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_EXTEN) | polarity;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable an External Trigger for Regular Channels
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_external_trigger_regular(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_EXTEN;
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_interrupts ADC Interrupt configuration API
* @ingroup adc_file
*
* @brief ADC Interrupt configuration API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_watchdog_interrupt(uint32_t adc)
{
ADC_IER(adc) |= ADC_IER_AWDIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Regular End-Of-Conversion Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_watchdog_interrupt(uint32_t adc)
{
ADC_IER(adc) &= ~ADC_IER_AWDIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Read the Analog Watchdog Flag
*
* This flag is set when the converted voltage crosses the high or low
* thresholds.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @returns bool true, if the signal is out of defined analog range.
*/
bool adc_get_watchdog_flag(uint32_t adc)
{
return ADC_ISR(adc) & ADC_ISR_AWD;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Clear Analog Watchdog Flag
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_clear_watchdog_flag(uint32_t adc)
{
ADC_ISR(adc) = ADC_ISR_AWD;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable the Overrun Interrupt
*
* The overrun interrupt is generated when data is not read from a result
* register before the next conversion is written. If DMA is enabled, all
* transfers are terminated and any conversion sequence is aborted.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_overrun_interrupt(uint32_t adc)
{
ADC_IER(adc) |= ADC_IER_OVRIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable the Overrun Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_overrun_interrupt(uint32_t adc)
{
ADC_IER(adc) &= ~ADC_IER_OVRIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Read the Overrun Flag
*
* The overrun flag is set when data is not read from a result register before
* the next conversion is written. If DMA is enabled, all transfers are
* terminated and any conversion sequence is aborted.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
bool adc_get_overrun_flag(uint32_t adc)
{
return ADC_ISR(adc) & ADC_ISR_OVR;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Clear Overrun Flags
*
* The overrun flag is cleared. Note that if an overrun occurs, DMA is
* terminated.
* The flag must be cleared and the DMA stream and ADC reinitialised to resume
* conversions (see the reference manual).
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_clear_overrun_flag(uint32_t adc)
{
ADC_ISR(adc) = ADC_ISR_OVR;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Regular End-Of-Conversion Sequence Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_eoc_sequence_interrupt(uint32_t adc)
{
ADC_IER(adc) |= ADC_IER_EOSEQIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Regular End-Of-Conversion Sequence Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_eoc_sequence_interrupt(uint32_t adc)
{
ADC_IER(adc) &= ~ADC_IER_EOSEQIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Read the Regular End-Of-Conversion Sequence Flag
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
bool adc_get_eoc_sequence_flag(uint32_t adc)
{
return ADC_ISR(adc) & ADC_ISR_EOSEQ;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Regular End-Of-Conversion Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_eoc_interrupt(uint32_t adc)
{
ADC_IER(adc) |= ADC_IER_EOCIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Regular End-Of-Conversion Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_eoc_interrupt(uint32_t adc)
{
ADC_IER(adc) &= ~ADC_IER_EOCIE;
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_config ADC Basic configuration API
* @ingroup adc_file
*
* @brief ADC Basic configuration API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Power Off
*
* Turn off the ADC to reduce power consumption to a few microamps.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_power_off(uint32_t adc)
{
ADC_CR(adc) &= ~ADC_CR_ADEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Power On
*
* If the ADC is in power-down mode then it is powered up. The application
* needs to wait a time of about 3 microseconds for stabilization before using
* the ADC. If the ADC is already on this function call will have no effect.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_power_on(uint32_t adc)
{
ADC_CR(adc) |= ADC_CR_ADEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Clock Prescale
*
* The ADC clock taken from the many sources.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] prescale Unsigned int32. Prescale value (@ref adc_api_clksource)
*/
void adc_set_clk_source(uint32_t adc, uint32_t source)
{
ADC_CFGR2(adc) = ((ADC_CFGR2(adc) & ~ADC_CFGR2_CKMODE) | source);
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set a Regular Channel Conversion Sequence
*
* Define a sequence of channels to be converted as a regular group with a
* length from 1 to 18 channels. If this is called during conversion, the
* current conversion is reset and conversion begins again with the newly
* defined group.
*
* @warning This core doesn't support the random order of ADC conversions.
* The channel list must be ordered by channel number.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] length Unsigned int8. Number of channels in the group.
* @param[in] channel Unsigned int8[]. Set of channels to convert, integers
* 0..18.
*/
void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[])
{
uint32_t reg32 = 0;
uint8_t i = 0;
bool stepup = false, stepdn = false;
if (length == 0) {
ADC_CHSELR(adc) = 0;
return;
}
reg32 |= (1 << channel[0]);
for (i = 1; i < length; i++) {
reg32 |= (1 << channel[i]);
stepup |= channel[i-1] < channel[i];
stepdn |= channel[i-1] > channel[i];
}
/* Check, if the channel list is in order */
if (stepup && stepdn) {
cm3_assert_not_reached();
}
/* Update the scan direction flag */
if (stepdn) {
ADC_CFGR1(adc) |= ADC_CFGR1_SCANDIR;
} else {
ADC_CFGR1(adc) &= ~ADC_CFGR1_SCANDIR;
}
ADC_CHSELR(adc) = reg32;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set the Sample Time for All Channels
*
* The sampling time can be selected in ADC clock cycles from 1.5 to 239.5,
* same for all channels.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] time Unsigned int8. Sampling time selection (@ref adc_api_smptime)
*/
void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time)
{
ADC_SMPR(adc) = time & ADC_SMPR_SMP;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Resolution
*
* ADC Resolution can be reduced from 12 bits to 10, 8 or 6 bits for a
* corresponding reduction in conversion time.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] resolution Unsigned int16. Resolution value (@ref adc_api_res)
*/
void adc_set_resolution(uint32_t adc, uint16_t resolution)
{
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_RES) | resolution;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set the Data as Left Aligned
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_set_left_aligned(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_ALIGN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set the Data as Right Aligned
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_set_right_aligned(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_ALIGN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable DMA Transfers
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_dma(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_DMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable DMA Transfers
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_dma(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_DMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable The Temperature Sensor
*
* This enables the sensor on channel 16
*/
void adc_enable_temperature_sensor(void)
{
ADC_CCR |= ADC_CCR_TSEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable The Temperature Sensor
*
* Disabling this will reduce power consumption from the temperature sensor
* measurement.
*/
void adc_disable_temperature_sensor(void)
{
ADC_CCR &= ~ADC_CCR_TSEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable The VRef Sensor
*
* This enables the reference voltage measurements on channel 17.
*/
void adc_enable_vref_sensor(void)
{
ADC_CCR |= ADC_CCR_VREFEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable The VRef Sensor
*
* Disabling this will reduce power consumption from the reference voltage
* measurement.
*/
void adc_disable_vref_sensor(void)
{
ADC_CCR &= ~ADC_CCR_VREFEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable The VBat Sensor
*
* This enables the battery voltage measurements on channel 17.
*/
void adc_enable_vbat_sensor(void)
{
ADC_CCR |= ADC_CCR_VBATEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable The VBat Sensor
*
* Disabling this will reduce power consumption from the battery voltage
* measurement.
*/
void adc_disable_vbat_sensor(void)
{
ADC_CCR &= ~ADC_CCR_VBATEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Start the calibration procedure
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_calibrate_start(uint32_t adc)
{
ADC_CR(adc) = ADC_CR_ADCAL;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Wait to finish the ADC calibration procedure
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_calibrate_wait_finish(uint32_t adc)
{
while (ADC_CR(adc) & ADC_CR_ADCAL);
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_wdg ADC Analog watchdog API
* @ingroup adc_file
*
* @brief ADC analog watchdog API definitions.
*
* The analog watchdog allows the monitoring of an analog signal between two
* threshold levels. The thresholds must be preset. Analog watchdog is disabled
* by default.
*
* @warning Comparison is done before data alignment takes place, so the
* thresholds are left-aligned.
*
* Example 1: Enable watchdog checking on all channels
*
* @code
* // in configuration
* adc_enable_analog_watchdog_on_all_channels(ADC1);
* adc_set_watchdog_high_threshold(ADC1, 0xE00);
* adc_set_watchdog_low_threshold(ADC1, 0x200);
*
* // in the main application thread
* if (adc_get_watchdog_flag(ADC1)) {
* // the converted signal is out of AWD ranges
* adc_clear_watchdog_flag(ADC1);
* }
* @endcode
*
* Example 2: Enable watchdog checking on channel 5
*
* @code
* // in configuration
* adc_enable_analog_watchdog_on_selected_channel(ADC1,5);
* adc_set_watchdog_high_threshold(ADC1, 0xE00);
* adc_set_watchdog_low_threshold(ADC1, 0x200);
*
* // in the main application thread
* if (adc_get_watchdog_flag(ADC1)) {
* // the converted signal is out of AWD ranges
* adc_clear_watchdog_flag(ADC1);
* }
* @endcode
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog for All Channels
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_analog_watchdog_on_all_channels(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_AWDEN;
ADC_CFGR1(adc) &= ~ADC_CFGR1_AWDSGL;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog for a Selected Channel
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] chan Unsigned int8. ADC channel number @ref adc_api_channel
*/
void adc_enable_analog_watchdog_on_selected_channel(uint32_t adc, uint8_t chan)
{
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_AWDCH) | \
ADC_CFGR1_AWDCH_VAL(chan);
ADC_CFGR1(adc) |= ADC_CFGR1_AWDEN | ADC_CFGR1_AWDSGL;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Analog Watchdog
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_analog_watchdog(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_AWDEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Analog Watchdog Upper Threshold
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] threshold Unsigned int8. Upper threshold value
*/
void adc_set_watchdog_high_threshold(uint32_t adc, uint8_t threshold)
{
ADC_TR(adc) = (ADC_TR(adc) & ~ADC_TR_HT) | ADC_TR_HT_VAL(threshold);
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Analog Watchdog Lower Threshold
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] threshold Unsigned int8. Lower threshold value
*/
void adc_set_watchdog_low_threshold(uint32_t adc, uint8_t threshold)
{
ADC_TR(adc) = (ADC_TR(adc) & ~ADC_TR_LT) | ADC_TR_LT_VAL(threshold);
}
/**@}*/
/*---------------------------------------------------------------------------*/
/**@}*/

View File

@ -0,0 +1,61 @@
/** @defgroup comp_file COMP
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx COMP</b>
*
* @version 1.0.0
*
* @date 10 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/comparator.h>
void comp_enable(uint8_t id)
{
COMP_CSR(id) |= COMP_CSR_EN;
}
void comp_disable(uint8_t id)
{
COMP_CSR(id) &= ~COMP_CSR_EN;
}
void comp_select_input(uint8_t id, uint32_t input)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_INSEL) | input;
}
void comp_select_output(uint8_t id, uint32_t output)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_OUTSEL) | output;
}
void comp_select_hyst(uint8_t id, uint32_t hyst)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_HYST) | hyst;
}
void comp_select_speed(uint8_t id, uint32_t speed)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_SPEED) | speed;
}

View File

@ -0,0 +1,33 @@
/** @defgroup crc_file CRC
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx CRC</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crc.h>
#include <libopencm3/stm32/common/crc_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dac_file DAC
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx DAC</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dac.h>
#include <libopencm3/stm32/common/dac_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dma_file DMA
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx DMA</b>
*
* @version 1.0.0
*
* @date 10 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/common/dma_common_l1f013.h>

View File

@ -0,0 +1,93 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/flash.h>
void flash_prefetch_buffer_enable(void)
{
FLASH_ACR |= FLASH_ACR_PRFTBE;
}
void flash_prefetch_buffer_disable(void)
{
FLASH_ACR &= ~FLASH_ACR_PRFTBE;
}
void flash_set_ws(uint32_t ws)
{
FLASH_ACR = (FLASH_ACR & ~FLASH_ACR_LATENCY) | ws;
}
void flash_wait_busy(void)
{
while ((FLASH_SR & FLASH_SR_BSY) != 0);
}
void flash_program_u32(uint32_t address, uint32_t data)
{
flash_wait_busy();
FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = (uint16_t)data;
flash_wait_busy();
MMIO16(address + 2) = data >> 16;
flash_wait_busy();
FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_u16(uint32_t address, uint16_t data)
{
flash_wait_busy();
FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = data;
flash_wait_busy();
FLASH_CR &= ~FLASH_CR_PG;
}
void flash_erase_page(uint32_t page_address)
{
flash_wait_busy();
FLASH_CR |= FLASH_CR_PER;
FLASH_AR = page_address;
FLASH_CR |= FLASH_CR_STRT;
flash_wait_busy();
FLASH_CR &= ~FLASH_CR_PER;
}
void flash_erase_all_pages(void)
{
flash_wait_busy();
FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_busy();
FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}

View File

@ -0,0 +1,31 @@
/** @defgroup gpio_file GPIO
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx General Purpose I/O</b>
*
* @version 1.0.0
*
* @date 18 August 2012
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/gpio.h>

View File

@ -0,0 +1,32 @@
/** @defgroup i2c_file I2C
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx I2C</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/i2c.h>

View File

@ -0,0 +1,33 @@
/** @defgroup iwdg_file IWDG
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx Independent Watchdog Timer</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/iwdg.h>
#include <libopencm3/stm32/common/iwdg_common_all.h>

View File

@ -0,0 +1,106 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Generic linker script for STM32 targets using libopencm3. */
/* Memory regions must be defined in the ld script which includes this one. */
/* Enforce emmition of the vector table. */
EXTERN (vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
/* Define sections. */
SECTIONS
{
.text : {
*(.vectors) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >rom
/* C++ Static constructors/destructors, also used for __attribute__
* ((constructor)) and the likes */
.preinit_array : {
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
} >rom
.init_array : {
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} >rom
.fini_array : {
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
} >rom
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >rom
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >rom
. = ALIGN(4);
_etext = .;
.data : {
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
_edata = .;
} >ram AT >rom
_data_loadaddr = LOADADDR(.data);
.bss : {
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/DISCARD/ : { *(.eh_frame) }
. = ALIGN(4);
end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

View File

@ -0,0 +1,38 @@
/** @defgroup pwr-file PWR
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx Power Control</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* This library supports the power control system for the
* STM32F0 series of ARM Cortex Microcontrollers by ST Microelectronics.
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/pwr.h>
/**@}*/

View File

@ -0,0 +1,637 @@
/** @defgroup STM32F0xx-rcc-file RCC
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx Reset and Clock Control</b>
*
* @version 1.0.0
*
* @date 29 Jun 2013
*
* This library supports the Reset and Clock Control System in the STM32F0xx
* series of ARM Cortex Microcontrollers by ST Microelectronics.
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/cm3/assert.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/flash.h>
uint32_t rcc_core_frequency = 8000000; /* 8MHz after reset */
uint32_t rcc_ppre_frequency = 8000000; /* 8MHz after reset */
/*---------------------------------------------------------------------------*/
/** @brief RCC Clear the Oscillator Ready Interrupt Flag
*
* Clear the interrupt flag that was set when a clock oscillator became ready
* to use.
*
* @param[in] osc enum ::osc_t. Oscillator ID
*/
void rcc_osc_ready_int_clear(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
RCC_CIR |= RCC_CIR_HSI14RDYC;
break;
case HSI:
RCC_CIR |= RCC_CIR_HSIRDYC;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYC;
break;
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYC;
break;
case LSE:
RCC_CIR |= RCC_CIR_LSERDYC;
break;
case LSI:
RCC_CIR |= RCC_CIR_LSIRDYC;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Enable the Oscillator Ready Interrupt
*
* @param[in] osc enum ::osc_t. Oscillator ID
*/
void rcc_osc_ready_int_enable(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
RCC_CIR |= RCC_CIR_HSI14RDYIE;
break;
case HSI:
RCC_CIR |= RCC_CIR_HSIRDYIE;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYIE;
break;
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE;
break;
case LSE:
RCC_CIR |= RCC_CIR_LSERDYIE;
break;
case LSI:
RCC_CIR |= RCC_CIR_LSIRDYIE;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Disable the Oscillator Ready Interrupt
*
* @param[in] osc enum ::osc_t. Oscillator ID
*/
void rcc_osc_ready_int_disable(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
RCC_CIR &= ~RCC_CIR_HSI14RDYC;
break;
case HSI:
RCC_CIR &= ~RCC_CIR_HSIRDYC;
break;
case HSE:
RCC_CIR &= ~RCC_CIR_HSERDYC;
break;
case PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYC;
break;
case LSE:
RCC_CIR &= ~RCC_CIR_LSERDYC;
break;
case LSI:
RCC_CIR &= ~RCC_CIR_LSIRDYC;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Read the Oscillator Ready Interrupt Flag
*
* @param[in] osc enum ::osc_t. Oscillator ID
* @returns int. Boolean value for flag set.
*/
int rcc_osc_ready_int_flag(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
return (RCC_CIR & RCC_CIR_HSI14RDYF) != 0;
break;
case HSI:
return (RCC_CIR & RCC_CIR_HSIRDYF) != 0;
break;
case HSE:
return (RCC_CIR & RCC_CIR_HSERDYF) != 0;
break;
case PLL:
return (RCC_CIR & RCC_CIR_PLLRDYF) != 0;
break;
case LSE:
return (RCC_CIR & RCC_CIR_LSERDYF) != 0;
break;
case LSI:
return (RCC_CIR & RCC_CIR_LSIRDYF) != 0;
break;
}
cm3_assert_not_reached();
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Clear the Clock Security System Interrupt Flag
*/
void rcc_css_int_clear(void)
{
RCC_CIR |= RCC_CIR_CSSC;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Read the Clock Security System Interrupt Flag
*
* @returns int. Boolean value for flag set.
*/
int rcc_css_int_flag(void)
{
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Wait for Oscillator Ready.
*
* @param[in] osc enum ::osc_t. Oscillator ID
*/
void rcc_wait_for_osc_ready(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
while ((RCC_CIR & RCC_CIR_HSI14RDYF) != 0);
break;
case HSI:
while ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
break;
case HSE:
while ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
break;
case PLL:
while ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
break;
case LSE:
while ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
break;
case LSI:
while ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Turn on an Oscillator.
*
* Enable an oscillator and power on. Each oscillator requires an amount of
* time to settle to a usable state. Refer to datasheets for time delay
* information. A status flag is available to indicate when the oscillator
* becomes ready (see @ref rcc_osc_ready_int_flag and @ref
* rcc_wait_for_osc_ready).
*
* @param[in] osc enum ::osc_t. Oscillator ID
*/
void rcc_osc_on(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
RCC_CR2 |= RCC_CR2_HSI14ON;
break;
case HSI:
RCC_CR |= RCC_CR_HSION;
break;
case HSE:
RCC_CR |= RCC_CR_HSEON;
break;
case LSE:
RCC_BDCR |= RCC_BDCR_LSEON;
break;
case LSI:
RCC_CSR |= RCC_CSR_LSION;
break;
case PLL:
/* don't do anything */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Turn off an Oscillator.
*
* Disable an oscillator and power off.
*
* @note An oscillator cannot be turned off if it is selected as the system
* clock.
*
* @param[in] osc enum ::osc_t. Oscillator ID
*/
void rcc_osc_off(enum rcc_osc osc)
{
switch (osc) {
case HSI14:
RCC_CR2 &= ~RCC_CR2_HSI14ON;
break;
case HSI:
RCC_CR &= ~RCC_CR_HSION;
break;
case HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
case LSE:
RCC_BDCR &= ~RCC_BDCR_LSEON;
break;
case LSI:
RCC_CSR &= ~RCC_CSR_LSION;
break;
case PLL:
/* don't do anything */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Enable the Clock Security System.
*/
void rcc_css_enable(void)
{
RCC_CR |= RCC_CR_CSSON;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Disable the Clock Security System.
*/
void rcc_css_disable(void)
{
RCC_CR &= ~RCC_CR_CSSON;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Enable Bypass.
*
* Enable an external clock to bypass the internal clock (high speed and low
* speed clocks only). The external clock must be enabled (see @ref rcc_osc_on)
* and the internal clock must be disabled (see @ref rcc_osc_off) for this to
* have effect.
*
* @param[in] osc enum ::osc_t. Oscillator ID. Only HSE and LSE have effect.
*/
void rcc_osc_bypass_enable(enum rcc_osc osc)
{
switch (osc) {
case HSE:
RCC_CR |= RCC_CR_HSEBYP;
break;
case LSE:
RCC_BDCR |= RCC_BDCR_LSEBYP;
break;
case HSI14:
case HSI:
case LSI:
case PLL:
/* Do nothing */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Disable Bypass.
*
* Re-enable the internal clock (high speed and low speed clocks only). The
* internal clock must be disabled (see @ref rcc_osc_off) for this to have
* effect.
*
*
* @param[in] osc enum ::osc_t. Oscillator ID. Only HSE and LSE have effect.
*/
void rcc_osc_bypass_disable(enum rcc_osc osc)
{
switch (osc) {
case HSE:
RCC_CR &= ~RCC_CR_HSEBYP;
break;
case LSE:
RCC_BDCR &= ~RCC_BDCR_LSEBYP;
break;
case HSI14:
case PLL:
case HSI:
case LSI:
/* Do nothing */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the Source for the System Clock.
*
* @param[in] osc enum ::osc_t. Oscillator ID. Only HSE, LSE and PLL have
* effect.
*/
void rcc_set_sysclk_source(enum rcc_osc clk)
{
switch (clk) {
case HSI:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI;
break;
case HSE:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSE;
break;
case PLL:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
break;
case LSI:
case LSE:
case HSI14:
/* do nothing */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the PLL Multiplication Factor.
*
* @note This only has effect when the PLL is disabled.
*
* @param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
*/
void rcc_set_pll_multiplication_factor(uint32_t mul)
{
RCC_CFGR = (RCC_CFGR & RCC_CFGR_PLLMUL) | mul;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the APB Prescale Factor.
*
* @note The APB1 clock frequency must not exceed 36MHz.
*
* @param[in] ppre1 Unsigned int32. APB prescale factor @ref rcc_cfgr_apb1pre
*/
void rcc_set_ppre(uint32_t ppre)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PPRE) | ppre;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the AHB Prescale Factor.
*
* @param[in] hpre Unsigned int32. AHB prescale factor @ref rcc_cfgr_ahbpre
*/
void rcc_set_hpre(uint32_t hpre)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_HPRE) | hpre;
}
void rcc_set_prediv(uint32_t prediv)
{
RCC_CFGR2 = (RCC_CFGR2 & ~RCC_CFGR2_PREDIV) | prediv;
}
void rcc_set_mco(uint32_t mcosrc)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_MCO) | mcosrc;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Get the System Clock Source.
*
* @returns ::osc_t System clock source:
*/
enum rcc_osc rcc_system_clock_source(void)
{
/* Return the clock source which is used as system clock. */
switch (RCC_CFGR & RCC_CFGR_SWS) {
case RCC_CFGR_SWS_HSI:
return HSI;
case RCC_CFGR_SWS_HSE:
return HSE;
case RCC_CFGR_SWS_PLL:
return PLL;
}
cm3_assert_not_reached();
}
void rcc_clock_setup_in_hsi_out_8mhz(void)
{
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
rcc_set_sysclk_source(HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_set_ws(FLASH_ACR_LATENCY_000_024MHZ);
rcc_ppre_frequency = 8000000;
rcc_core_frequency = 8000000;
}
void rcc_clock_setup_in_hsi_out_16mhz(void)
{
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
rcc_set_sysclk_source(HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_set_ws(FLASH_ACR_LATENCY_000_024MHZ);
/* 8MHz * 4 / 2 = 16MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL4);
RCC_CFGR &= RCC_CFGR_PLLSRC;
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
rcc_set_sysclk_source(PLL);
rcc_ppre_frequency = 16000000;
rcc_core_frequency = 16000000;
}
void rcc_clock_setup_in_hsi_out_24mhz(void)
{
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
rcc_set_sysclk_source(HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_set_ws(FLASH_ACR_LATENCY_000_024MHZ);
/* 8MHz * 6 / 2 = 24MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL6);
RCC_CFGR &= RCC_CFGR_PLLSRC;
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
rcc_set_sysclk_source(PLL);
rcc_ppre_frequency = 24000000;
rcc_core_frequency = 24000000;
}
void rcc_clock_setup_in_hsi_out_32mhz(void)
{
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
rcc_set_sysclk_source(HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_set_ws(FLASH_ACR_LATENCY_024_048MHZ);
/* 8MHz * 8 / 2 = 32MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL8);
RCC_CFGR &= RCC_CFGR_PLLSRC;
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
rcc_set_sysclk_source(PLL);
rcc_ppre_frequency = 32000000;
rcc_core_frequency = 32000000;
}
void rcc_clock_setup_in_hsi_out_40mhz(void)
{
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
rcc_set_sysclk_source(HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_set_ws(FLASH_ACR_LATENCY_024_048MHZ);
/* 8MHz * 10 / 2 = 40MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL10);
RCC_CFGR &= RCC_CFGR_PLLSRC;
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
rcc_set_sysclk_source(PLL);
rcc_ppre_frequency = 32000000;
rcc_core_frequency = 32000000;
}
void rcc_clock_setup_in_hsi_out_48mhz(void)
{
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
rcc_set_sysclk_source(HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_set_ws(FLASH_ACR_LATENCY_024_048MHZ);
/* 8MHz * 12 / 2 = 24MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL16);
RCC_CFGR &= RCC_CFGR_PLLSRC;
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
rcc_set_sysclk_source(PLL);
rcc_ppre_frequency = 48000000;
rcc_core_frequency = 48000000;
}
#define _RCC_REG(i) MMIO32(RCC_BASE + ((i) >> 5))
#define _RCC_BIT(i) (1 << ((i) & 0x1f))
void rcc_periph_clock_enable(enum rcc_periph_clken periph)
{
_RCC_REG(periph) |= _RCC_BIT(periph);
}
void rcc_periph_clock_disable(enum rcc_periph_clken periph)
{
_RCC_REG(periph) &= ~_RCC_BIT(periph);
}
void rcc_periph_reset_pulse(enum rcc_periph_rst periph)
{
_RCC_REG(periph) |= _RCC_BIT(periph);
_RCC_REG(periph) &= ~_RCC_BIT(periph);
}
void rcc_periph_reset_hold(enum rcc_periph_rst periph)
{
_RCC_REG(periph) |= _RCC_BIT(periph);
}
void rcc_periph_reset_release(enum rcc_periph_rst periph)
{
_RCC_REG(periph) &= ~_RCC_BIT(periph);
}
#undef _RCC_REG
#undef _RCC_BIT
/**@}*/

View File

@ -0,0 +1,32 @@
/** @defgroup rtc_file RTC
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx RTC</b>
*
* @version 1.0.0
*
* @date 10 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/rtc.h>
#include <libopencm3/stm32/common/rtc_common_l1f024.h>

View File

@ -0,0 +1,54 @@
/** @defgroup spi_file SPI
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx Serial Peripheral Interface</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/rcc.h>
void spi_set_data_size(uint32_t spi, uint16_t data_s)
{
SPI_CR2(spi) = (SPI_CR2(spi) & ~SPI_CR2_DS_MASK) |
(data_s & SPI_CR2_DS_MASK);
}
void spi_fifo_reception_threshold_8bit(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_FRXTH;
}
void spi_fifo_reception_threshold_16bit(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_FRXTH;
}
void spi_i2s_mode_spi_mode(uint32_t spi)
{
SPI_I2SCFGR(spi) &= ~SPI_I2SCFGR_I2SMOD;
}

View File

@ -0,0 +1,31 @@
/** @defgroup syscfg_file SYSCFG
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx SYSCFG</b>
*
* @version 1.0.0
*
* @date 10 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/syscfg.h>

View File

@ -0,0 +1,34 @@
/** @defgroup timer_file Timers
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx Timers</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/timer.h>

View File

@ -0,0 +1,429 @@
/** @defgroup usart_file USART
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx USART</b>
*
* @version 1.0.0
*
* @date 7 Jul 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/rcc.h>
/*---------------------------------------------------------------------------*/
/** @brief USART Set Baudrate.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] baud unsigned 32 bit. Baud rate specified in Hz.
*/
void usart_set_baudrate(uint32_t usart, uint32_t baud)
{
uint32_t clock = rcc_ppre_frequency;
if (usart == USART1) {
clock = rcc_ppre_frequency;
/* TODO selective PCLK, SYSCLK, HSI or LSE */
}
/* TODO check oversampling 16 */
USART_BRR(usart) = ((2 * clock) + baud) / (2 * baud);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Word Length.
*
* The word length is set to 8 or 9 bits. Note that the last bit will be a
* parity bit if parity is enabled, in which case the data length will be 7
* or 8 bits respectively.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] bits unsigned 32 bit. Word length in bits 8 or 9.
*/
void usart_set_databits(uint32_t usart, uint32_t bits)
{
if (bits == 8) {
USART_CR1(usart) &= ~USART_CR1_M; /* 8 data bits */
} else {
USART_CR1(usart) |= USART_CR1_M; /* 9 data bits */
}
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Stop Bit(s).
*
* The stop bits are specified as 0.5, 1, 1.5 or 2.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] stopbits unsigned 32 bit. Stop bits @ref usart_cr2_stopbits.
*/
void usart_set_stopbits(uint32_t usart, uint32_t stopbits)
{
USART_CR2(usart) = (USART_CR2(usart) & ~USART_CR2_STOP) | stopbits;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Parity.
*
* The parity bit can be selected as none, even or odd.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] parity unsigned 32 bit. Parity @ref usart_cr1_parity.
*/
void usart_set_parity(uint32_t usart, uint32_t parity)
{
USART_CR1(usart) = (USART_CR1(usart) & ~USART_PARITY) | parity;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Rx/Tx Mode.
*
* The mode can be selected as Rx only, Tx only or Rx+Tx.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] mode unsigned 32 bit. Mode @ref usart_cr1_mode.
*/
void usart_set_mode(uint32_t usart, uint32_t mode)
{
USART_CR1(usart) = (USART_CR1(usart) & ~USART_MODE) | mode;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Set Hardware Flow Control.
*
* The flow control bit can be selected as none, RTS, CTS or RTS+CTS.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] flowcontrol unsigned 32 bit. Flowcontrol @ref
* usart_cr3_flowcontrol.
*/
void usart_set_flow_control(uint32_t usart, uint32_t flowctrl)
{
USART_CR3(usart) = (USART_CR3(usart) & ~USART_FLOWCONTROL) | flowctrl;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Enable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_enable(uint32_t usart)
{
USART_CR1(usart) |= USART_CR1_UE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Disable.
*
* At the end of the current frame, the USART is disabled to reduce power.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_disable(uint32_t usart)
{
USART_CR1(usart) &= ~USART_CR1_UE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Send a Data Word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] data unsigned 16 bit.
*/
void usart_send(uint32_t usart, uint8_t data)
{
USART_TDR(usart) = data;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word.
*
* If parity is enabled the MSB (bit 7 or 8 depending on the word length) is
* the parity bit.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @returns unsigned 16 bit data word.
*/
uint8_t usart_recv(uint32_t usart)
{
/* Receive data. */
return USART_RDR(usart);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Wait for Transmit Data Buffer Empty
*
* Blocks until the transmit data buffer becomes empty and is ready to accept
* the next data word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_wait_send_ready(uint32_t usart)
{
/* Wait until the data has been transferred into the shift register. */
while ((USART_ISR(usart) & USART_ISR_TXE) == 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Wait for Received Data Available
*
* Blocks until the receive data buffer holds a valid received data word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_wait_recv_ready(uint32_t usart)
{
/* Wait until the data is ready to be received. */
while ((USART_ISR(usart) & USART_ISR_RXNE) == 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Send Data Word with Blocking
*
* Blocks until the transmit data buffer becomes empty then writes the next
* data word for transmission.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] data unsigned 16 bit.
*/
void usart_send_blocking(uint32_t usart, uint8_t data)
{
usart_wait_send_ready(usart);
usart_send(usart, data);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word with Blocking.
*
* Wait until a data word has been received then return the word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @returns unsigned 16 bit data word.
*/
uint8_t usart_recv_blocking(uint32_t usart)
{
usart_wait_recv_ready(usart);
return usart_recv(usart);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver DMA Enable.
*
* DMA is available on:
* @li USART1 Rx DMA1 channel 3 or 5.
* @li USART2 Rx DMA1 channel 5.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_enable_rx_dma(uint32_t usart)
{
USART_CR3(usart) |= USART_CR3_DMAR;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver DMA Disable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_disable_rx_dma(uint32_t usart)
{
USART_CR3(usart) &= ~USART_CR3_DMAR;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter DMA Enable.
*
* DMA is available on:
* @li USART1 Tx DMA1 channel 2 or 4.
* @li USART2 Tx DMA1 channel 4.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_enable_tx_dma(uint32_t usart)
{
USART_CR3(usart) |= USART_CR3_DMAT;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter DMA Disable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_disable_tx_dma(uint32_t usart)
{
USART_CR3(usart) &= ~USART_CR3_DMAT;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver Interrupt Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref
usart_reg_base
*/
void usart_enable_rx_interrupt(uint32_t usart)
{
USART_CR1(usart) |= USART_CR1_RXNEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Receiver Interrupt Disable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_disable_rx_interrupt(uint32_t usart)
{
USART_CR1(usart) &= ~USART_CR1_RXNEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter Interrupt Enable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_enable_tx_interrupt(uint32_t usart)
{
USART_CR1(usart) |= USART_CR1_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Transmitter Interrupt Disable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_disable_tx_interrupt(uint32_t usart)
{
USART_CR1(usart) &= ~USART_CR1_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Error Interrupt Enable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_enable_error_interrupt(uint32_t usart)
{
USART_CR3(usart) |= USART_CR3_EIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Error Interrupt Disable.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_disable_error_interrupt(uint32_t usart)
{
USART_CR3(usart) &= ~USART_CR3_EIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Status Flag.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
* @returns boolean: flag set.
*/
bool usart_get_flag(uint32_t usart, uint32_t flag)
{
return ((USART_ISR(usart) & flag) != 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Return Interrupt Source.
*
* Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was
* set and the interrupt was enabled. If the specified flag is not an interrupt
* flag, the function returns false.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
* @returns boolean: flag and interrupt enable both set.
*/
bool usart_get_interrupt_source(uint32_t usart, uint32_t flag)
{
uint32_t flag_set = (USART_ISR(usart) & flag);
/* IDLE, RXNE, TC, TXE interrupts */
if ((flag >= USART_ISR_IDLE) && (flag <= USART_ISR_TXE)) {
return ((flag_set & USART_CR1(usart)) != 0);
/* Overrun error */
} else if (flag == USART_ISR_ORE) {
return flag_set && (USART_CR3(usart) & USART_CR3_CTSIE);
}
return false;
}
/**@}*/

View File

@ -0,0 +1,51 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32f1
PREFIX ?= arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g \
-Wall -Wextra -Wimplicit-function-declaration \
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wshadow \
-I../../../include -fno-common \
-mcpu=cortex-m3 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F1
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = adc.o can.o desig.o ethernet.o flash.o gpio.o \
rcc.o rtc.o timer.o
OBJS += crc_common_all.o dac_common_all.o dma_common_l1f013.o \
gpio_common_all.o i2c_common_all.o iwdg_common_all.o \
pwr_common_all.o spi_common_all.o spi_common_f124.o \
timer_common_all.o usart_common_all.o usart_common_f124.o \
exti_common_all.o
OBJS += usb.o usb_control.o usb_standard.o usb_f103.o usb_f107.o \
usb_fx07_common.o
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
/** @defgroup crc_file CRC
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx CRC</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crc.h>
#include <libopencm3/stm32/common/crc_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dac_file DAC
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx DAC</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dac.h>
#include <libopencm3/stm32/common/dac_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dma_file DMA
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx DMA</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/common/dma_common_l1f013.h>

View File

@ -0,0 +1,52 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/ethernet.h>
void eth_smi_write(uint8_t phy, uint8_t reg, uint16_t data)
{
/* Set PHY and register addresses for write access. */
ETH_MACMIIAR &= ~(ETH_MACMIIAR_MR | ETH_MACMIIAR_PA);
ETH_MACMIIAR |= (phy << 11) | (reg << 6) | ETH_MACMIIAR_MW;
/* Set register value. */
ETH_MACMIIDR = data;
/* Begin transaction. */
ETH_MACMIIAR |= ETH_MACMIIAR_MB;
/* Wait for not busy. */
while (ETH_MACMIIAR & ETH_MACMIIAR_MB);
}
uint16_t eth_smi_read(uint8_t phy, uint8_t reg)
{
/* Set PHY and register addresses for write access. */
ETH_MACMIIAR &= ~(ETH_MACMIIAR_MR | ETH_MACMIIAR_PA | ETH_MACMIIAR_MW);
ETH_MACMIIAR |= (phy << 11) | (reg << 6);
/* Begin transaction. */
ETH_MACMIIAR |= ETH_MACMIIAR_MB;
/* Wait for not busy. */
while (ETH_MACMIIAR & ETH_MACMIIAR_MB);
/* Set register value. */
return (uint16_t)(ETH_MACMIIDR);
}

View File

@ -0,0 +1,202 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/flash.h>
void flash_prefetch_buffer_enable(void)
{
FLASH_ACR |= FLASH_ACR_PRFTBE;
}
void flash_prefetch_buffer_disable(void)
{
FLASH_ACR &= ~FLASH_ACR_PRFTBE;
}
void flash_halfcycle_enable(void)
{
FLASH_ACR |= FLASH_ACR_HLFCYA;
}
void flash_halfcycle_disable(void)
{
FLASH_ACR &= ~FLASH_ACR_HLFCYA;
}
void flash_set_ws(uint32_t ws)
{
uint32_t reg32;
reg32 = FLASH_ACR;
reg32 &= ~((1 << 0) | (1 << 1) | (1 << 2));
reg32 |= ws;
FLASH_ACR = reg32;
}
void flash_unlock(void)
{
/* Clear the unlock state. */
FLASH_CR |= FLASH_CR_LOCK;
/* Authorize the FPEC access. */
FLASH_KEYR = FLASH_KEYR_KEY1;
FLASH_KEYR = FLASH_KEYR_KEY2;
}
void flash_lock(void)
{
FLASH_CR |= FLASH_CR_LOCK;
}
void flash_clear_pgerr_flag(void)
{
FLASH_SR |= FLASH_SR_PGERR;
}
void flash_clear_eop_flag(void)
{
FLASH_SR |= FLASH_SR_EOP;
}
void flash_clear_wrprterr_flag(void)
{
FLASH_SR |= FLASH_SR_WRPRTERR;
}
void flash_clear_bsy_flag(void)
{
FLASH_SR &= ~FLASH_SR_BSY;
}
void flash_clear_status_flags(void)
{
flash_clear_pgerr_flag();
flash_clear_eop_flag();
flash_clear_wrprterr_flag();
flash_clear_bsy_flag();
}
uint32_t flash_get_status_flags(void)
{
return FLASH_SR &= (FLASH_SR_PGERR |
FLASH_SR_EOP |
FLASH_SR_WRPRTERR |
FLASH_SR_BSY);
}
void flash_unlock_option_bytes(void)
{
/* F1 uses same keys for flash and option */
FLASH_OPTKEYR = FLASH_KEYR_KEY1;
FLASH_OPTKEYR = FLASH_KEYR_KEY2;
}
void flash_wait_for_last_operation(void)
{
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY);
}
void flash_program_word(uint32_t address, uint32_t data)
{
/* Ensure that all flash operations are complete. */
flash_wait_for_last_operation();
/* Enable writes to flash. */
FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO16(address) = (uint16_t)data;
/* Wait for the write to complete. */
flash_wait_for_last_operation();
/* Program the second half of the word. */
MMIO16(address + 2) = data >> 16;
/* Wait for the write to complete. */
flash_wait_for_last_operation();
/* Disable writes to flash. */
FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_half_word(uint32_t address, uint16_t data)
{
flash_wait_for_last_operation();
FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = data;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_erase_page(uint32_t page_address)
{
flash_wait_for_last_operation();
FLASH_CR |= FLASH_CR_PER;
FLASH_AR = page_address;
FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_PER;
}
void flash_erase_all_pages(void)
{
flash_wait_for_last_operation();
FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}
void flash_erase_option_bytes(void)
{
flash_wait_for_last_operation();
if ((FLASH_CR & FLASH_CR_OPTWRE) == 0) {
flash_unlock_option_bytes();
}
FLASH_CR |= FLASH_CR_OPTER; /* Enable option byte erase. */
FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_OPTER; /* Disable option byte erase. */
}
void flash_program_option_bytes(uint32_t address, uint16_t data)
{
flash_wait_for_last_operation();
if ((FLASH_CR & FLASH_CR_OPTWRE) == 0) {
flash_unlock_option_bytes();
}
FLASH_CR |= FLASH_CR_OPTPG; /* Enable option byte programming. */
MMIO16(address) = data;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_OPTPG; /* Disable option byte programming. */
}

View File

@ -0,0 +1,194 @@
/** @defgroup gpio_file GPIO
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx General Purpose I/O</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2009
Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
@date 18 August 2012
Each I/O port has 16 individually configurable bits. Many I/O pins share GPIO
functionality with a number of alternate functions and must be configured to
the alternate function mode if these are to be accessed. A feature is available
to remap alternative functions to a limited set of alternative pins in the
event of a clash of requirements.
The data registers associated with each port for input and output are 32 bit
with the upper 16 bits unused. The output buffer must be written as a 32 bit
word, but individual bits may be set or reset separately in atomic operations
to avoid race conditions during interrupts. Bits may also be individually
locked to prevent accidental configuration changes. Once locked the
configuration cannot be changed until after the next reset.
Each port bit can be configured as analog or digital input, the latter can be
floating or pulled up or down. As outputs they can be configured as either
push-pull or open drain, digital I/O or alternate function, and with maximum
output speeds of 2MHz, 10MHz, or 50MHz.
On reset all ports are configured as digital floating input.
@section gpio_api_ex Basic GPIO Handling API.
Example 1: Push-pull digital output actions on ports C2 and C9
@code
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2 | GPIO9);
gpio_set(GPIOC, GPIO2 | GPIO9);
gpio_clear(GPIOC, GPIO2);
gpio_toggle(GPIOC, GPIO2 | GPIO9);
gpio_port_write(GPIOC, 0x204);
@endcode
Example 1: Digital input on port C12
@code
gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT, GPIO12);
reg16 = gpio_port_read(GPIOC);
@endcode
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/gpio.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief Set GPIO Pin Mode
Sets the mode (input/output) and configuration (analog/digitial and
open drain/push pull), for a set of GPIO pins on a given GPIO port.
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] mode Unsigned int8. Pin mode @ref gpio_mode
@param[in] cnf Unsigned int8. Pin configuration @ref gpio_cnf
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
If multiple pins are to be set, use logical OR '|' to separate
them.
*/
void gpio_set_mode(uint32_t gpioport, uint8_t mode, uint8_t cnf, uint16_t gpios)
{
uint16_t i, offset = 0;
uint32_t crl = 0, crh = 0, tmp32 = 0;
/*
* We want to set the config only for the pins mentioned in gpios,
* but keeping the others, so read out the actual config first.
*/
crl = GPIO_CRL(gpioport);
crh = GPIO_CRH(gpioport);
/* Iterate over all bits, use i as the bitnumber. */
for (i = 0; i < 16; i++) {
/* Only set the config if the bit is set in gpios. */
if (!((1 << i) & gpios)) {
continue;
}
/* Calculate bit offset. */
offset = (i < 8) ? (i * 4) : ((i - 8) * 4);
/* Use tmp32 to either modify crl or crh. */
tmp32 = (i < 8) ? crl : crh;
/* Modify bits are needed. */
tmp32 &= ~(0xf << offset); /* Clear the bits first. */
tmp32 |= (mode << offset) | (cnf << (offset + 2));
/* Write tmp32 into crl or crh, leave the other unchanged. */
crl = (i < 8) ? tmp32 : crl;
crh = (i >= 8) ? tmp32 : crh;
}
GPIO_CRL(gpioport) = crl;
GPIO_CRH(gpioport) = crh;
}
/*---------------------------------------------------------------------------*/
/** @brief Map the EVENTOUT signal
Enable the EVENTOUT signal and select the port and pin to be used.
@param[in] evoutport Unsigned int8. Port for EVENTOUT signal @ref afio_evcr_port
@param[in] evoutpin Unsigned int8. Pin for EVENTOUT signal @ref afio_evcr_pin
*/
void gpio_set_eventout(uint8_t evoutport, uint8_t evoutpin)
{
AFIO_EVCR = AFIO_EVCR_EVOE | evoutport | evoutpin;
}
/*---------------------------------------------------------------------------*/
/** @brief Map Alternate Function Port Bits (Main Set)
A number of alternate function ports can be remapped to defined alternative
port bits to avoid clashes in cases where multiple alternate functions are
present. Refer to the datasheets for the particular mapping desired. This
provides the main set of remap functionality. See @ref gpio_secondary_remap for
a number of lesser used remaps.
The AFIO remapping feature is used only with the STM32F10x series.
@note The Serial Wire JTAG disable controls allow certain GPIO ports to become
available in place of some of the SWJ signals. Full SWJ capability is obtained
by setting this to zero. The value of this must be specified for every call to
this function as its current value cannot be ascertained from the hardware.
@param[in] swjdisable Unsigned int8. Disable parts of the SWJ capability @ref
afio_swj_disable.
@param[in] maps Unsigned int32. Logical OR of map enable controls from @ref
afio_remap, @ref afio_remap_can1, @ref afio_remap_tim3, @ref afio_remap_tim2,
@ref afio_remap_tim1, @ref afio_remap_usart3. For connectivity line devices
only @ref afio_remap_cld are also available.
*/
void gpio_primary_remap(uint32_t swjdisable, uint32_t maps)
{
AFIO_MAPR |= (swjdisable & AFIO_MAPR_SWJ_MASK) | (maps & 0x1FFFFF);
}
/*---------------------------------------------------------------------------*/
/** @brief Map Alternate Function Port Bits (Secondary Set)
A number of alternate function ports can be remapped to defined alternative
port bits to avoid clashes in cases where multiple alternate functions are
present. Refer to the datasheets for the particular mapping desired. This
provides the second smaller and less used set of remap functionality. See @ref
gpio_primary_remap for the main set of remaps.
The AFIO remapping feature is used only with the STM32F10x series.
@param[in] maps Unsigned int32. Logical OR of map enable controls from @ref
afio_remap2
*/
void gpio_secondary_remap(uint32_t maps)
{
AFIO_MAPR2 |= maps;
}
/**@}*/

View File

@ -0,0 +1,33 @@
/** @defgroup i2c_file I2C
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx I2C</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/stm32/common/i2c_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup iwdg_file IWDG
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx Independent Watchdog Timer</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/iwdg.h>
#include <libopencm3/stm32/common/iwdg_common_all.h>

View File

@ -0,0 +1,106 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Generic linker script for STM32 targets using libopencm3. */
/* Memory regions must be defined in the ld script which includes this one. */
/* Enforce emmition of the vector table. */
EXTERN (vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
/* Define sections. */
SECTIONS
{
.text : {
*(.vectors) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >rom
/* C++ Static constructors/destructors, also used for __attribute__
* ((constructor)) and the likes */
.preinit_array : {
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
} >rom
.init_array : {
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} >rom
.fini_array : {
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
} >rom
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >rom
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >rom
. = ALIGN(4);
_etext = .;
.data : {
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
_edata = .;
} >ram AT >rom
_data_loadaddr = LOADADDR(.data);
.bss : {
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/DISCARD/ : { *(.eh_frame) }
. = ALIGN(4);
end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

View File

@ -0,0 +1,43 @@
/** @defgroup pwr-file PWR
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx Power Control</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2012
Ken Sarkies <ksarkies@internode.on.net>
@date 18 August 2012
This library supports the power control system for the
STM32F1 series of ARM Cortex Microcontrollers by ST Microelectronics.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/pwr.h>
/**@}*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,301 @@
/** @defgroup rtc_file RTC
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx RTC</b>
@author @htmlonly &copy; @endhtmlonly 2010 Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2010 Lord James <lordjames@y7mail.com>
@version 1.0.0
@date 4 March 2013
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2010 Lord James <lordjames@y7mail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/rtc.h>
#include <libopencm3/stm32/pwr.h>
void rtc_awake_from_off(osc_t clock_source)
{
uint32_t reg32;
/* Enable power and backup interface clocks. */
RCC_APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
/* Enable access to the backup registers and the RTC. */
PWR_CR |= PWR_CR_DBP;
/*
* Reset the backup domain, clears everything RTC related.
* If not wanted use the rtc_awake_from_standby() function.
*/
rcc_backupdomain_reset();
switch (clock_source) {
case LSE:
/* Turn the LSE on and wait while it stabilises. */
RCC_BDCR |= RCC_BDCR_LSEON;
while ((reg32 = (RCC_BDCR & RCC_BDCR_LSERDY)) == 0);
/* Choose LSE as the RTC clock source. */
RCC_BDCR &= ~((1 << 8) | (1 << 9));
RCC_BDCR |= (1 << 8);
break;
case LSI:
/* Turn the LSI on and wait while it stabilises. */
RCC_CSR |= RCC_CSR_LSION;
while ((reg32 = (RCC_CSR & RCC_CSR_LSIRDY)) == 0);
/* Choose LSI as the RTC clock source. */
RCC_BDCR &= ~((1 << 8) | (1 << 9));
RCC_BDCR |= (1 << 9);
break;
case HSE:
/* Turn the HSE on and wait while it stabilises. */
RCC_CR |= RCC_CR_HSEON;
while ((reg32 = (RCC_CR & RCC_CR_HSERDY)) == 0);
/* Choose HSE as the RTC clock source. */
RCC_BDCR &= ~((1 << 8) | (1 << 9));
RCC_BDCR |= (1 << 9) | (1 << 8);
break;
case PLL:
case PLL2:
case PLL3:
case HSI:
/* Unusable clock source, here to prevent warnings. */
/* Turn off clock sources to RTC. */
RCC_BDCR &= ~((1 << 8) | (1 << 9));
break;
}
/* Enable the RTC. */
RCC_BDCR |= RCC_BDCR_RTCEN;
/* Wait for the RSF bit in RTC_CRL to be set by hardware. */
RTC_CRL &= ~RTC_CRL_RSF;
while ((reg32 = (RTC_CRL & RTC_CRL_RSF)) == 0);
/* Wait for the last write operation to finish. */
/* TODO: Necessary? */
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
}
void rtc_enter_config_mode(void)
{
uint32_t reg32;
/* Wait until the RTOFF bit is 1 (no RTC register writes ongoing). */
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
/* Enter configuration mode. */
RTC_CRL |= RTC_CRL_CNF;
}
void rtc_exit_config_mode(void)
{
uint32_t reg32;
/* Exit configuration mode. */
RTC_CRL &= ~RTC_CRL_CNF;
/* Wait until the RTOFF bit is 1 (our RTC register write finished). */
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
}
void rtc_set_alarm_time(uint32_t alarm_time)
{
rtc_enter_config_mode();
RTC_ALRL = (alarm_time & 0x0000ffff);
RTC_ALRH = (alarm_time & 0xffff0000) >> 16;
rtc_exit_config_mode();
}
void rtc_enable_alarm(void)
{
rtc_enter_config_mode();
RTC_CRH |= RTC_CRH_ALRIE;
rtc_exit_config_mode();
}
void rtc_disable_alarm(void)
{
rtc_enter_config_mode();
RTC_CRH &= ~RTC_CRH_ALRIE;
rtc_exit_config_mode();
}
void rtc_set_prescale_val(uint32_t prescale_val)
{
rtc_enter_config_mode();
RTC_PRLL = prescale_val & 0x0000ffff; /* PRL[15:0] */
RTC_PRLH = (prescale_val & 0x000f0000) >> 16; /* PRL[19:16] */
rtc_exit_config_mode();
}
uint32_t rtc_get_counter_val(void)
{
return (RTC_CNTH << 16) | RTC_CNTL;
}
uint32_t rtc_get_prescale_div_val(void)
{
return (RTC_DIVH << 16) | RTC_DIVL;
}
uint32_t rtc_get_alarm_val(void)
{
return (RTC_ALRH << 16) | RTC_ALRL;
}
void rtc_set_counter_val(uint32_t counter_val)
{
rtc_enter_config_mode();
RTC_CNTH = (counter_val & 0xffff0000) >> 16; /* CNT[31:16] */
RTC_CNTL = counter_val & 0x0000ffff; /* CNT[15:0] */
rtc_exit_config_mode();
}
void rtc_interrupt_enable(rtcflag_t flag_val)
{
rtc_enter_config_mode();
/* Set the correct interrupt enable. */
switch (flag_val) {
case RTC_SEC:
RTC_CRH |= RTC_CRH_SECIE;
break;
case RTC_ALR:
RTC_CRH |= RTC_CRH_ALRIE;
break;
case RTC_OW:
RTC_CRH |= RTC_CRH_OWIE;
break;
}
rtc_exit_config_mode();
}
void rtc_interrupt_disable(rtcflag_t flag_val)
{
rtc_enter_config_mode();
/* Disable the correct interrupt enable. */
switch (flag_val) {
case RTC_SEC:
RTC_CRH &= ~RTC_CRH_SECIE;
break;
case RTC_ALR:
RTC_CRH &= ~RTC_CRH_ALRIE;
break;
case RTC_OW:
RTC_CRH &= ~RTC_CRH_OWIE;
break;
}
rtc_exit_config_mode();
}
void rtc_clear_flag(rtcflag_t flag_val)
{
/* Configuration mode not needed. */
/* Clear the correct flag. */
switch (flag_val) {
case RTC_SEC:
RTC_CRL &= ~RTC_CRL_SECF;
break;
case RTC_ALR:
RTC_CRL &= ~RTC_CRL_ALRF;
break;
case RTC_OW:
RTC_CRL &= ~RTC_CRL_OWF;
break;
}
}
uint32_t rtc_check_flag(rtcflag_t flag_val)
{
uint32_t reg32;
/* Read correct flag. */
switch (flag_val) {
case RTC_SEC:
reg32 = RTC_CRL & RTC_CRL_SECF;
break;
case RTC_ALR:
reg32 = RTC_CRL & RTC_CRL_ALRF;
break;
case RTC_OW:
reg32 = RTC_CRL & RTC_CRL_OWF;
break;
default:
reg32 = 0;
break;
}
return reg32;
}
void rtc_awake_from_standby(void)
{
uint32_t reg32;
/* Enable power and backup interface clocks. */
RCC_APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
/* Enable access to the backup registers and the RTC. */
PWR_CR |= PWR_CR_DBP;
/* Wait for the RSF bit in RTC_CRL to be set by hardware. */
RTC_CRL &= ~RTC_CRL_RSF;
while ((reg32 = (RTC_CRL & RTC_CRL_RSF)) == 0);
/* Wait for the last write operation to finish. */
/* TODO: Necessary? */
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
}
void rtc_auto_awake(osc_t clock_source, uint32_t prescale_val)
{
uint32_t reg32;
/* Enable power and backup interface clocks. */
RCC_APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
/* Enable access to the backup registers and the RTC. */
/* TODO: Not sure if this is necessary to just read the flag. */
PWR_CR |= PWR_CR_DBP;
reg32 = RCC_BDCR & RCC_BDCR_RTCEN;
if (reg32 != 0) {
rtc_awake_from_standby();
} else {
rtc_awake_from_off(clock_source);
rtc_set_prescale_val(prescale_val);
}
}

View File

@ -0,0 +1,32 @@
/** @defgroup spi_file SPI
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx SPI</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/common/spi_common_all.h>

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x6, 32K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x8, 64K flash, 8K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100xB, 128K flash, 8K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100xC, 256K flash, 24K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 24K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100xD, 384K flash, 32K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 384K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100xE, 512K flash, 32K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@ -0,0 +1,58 @@
/* This file is used for documentation purposes. It does not need
to be compiled. All source code is in the common area.
If there is any device specific code required it can be included here,
in which case this file must be added to the compile list. */
/** @defgroup timer_file Timers
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx Timers</b>
@version 1.0.0
@date 18 August 2012
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/common/timer_common_all.h>
/*---------------------------------------------------------------------------*/
/** @brief Set Input Polarity
@param[in] timer_peripheral Unsigned int32. Timer register address base
@param[in] ic ::tim_ic_id. Input Capture channel designator.
@param[in] pol ::tim_ic_pol. Input Capture polarity.
*/
void timer_ic_set_polarity(uint32_t timer_peripheral, enum tim_ic_id ic,
enum tim_ic_pol pol)
{
if (pol) {
TIM_CCER(timer_peripheral) |= (0x2 << (ic * 4));
} else {
TIM_CCER(timer_peripheral) &= ~(0x2 << (ic * 4));
}
}

View File

@ -0,0 +1,33 @@
/** @defgroup usart_file USART
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx USART</b>
@version 1.0.0
@date 30 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/common/usart_common_all.h>

View File

@ -0,0 +1,48 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32f2
PREFIX ?= arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g \
-Wall -Wextra -Wimplicit-function-declaration \
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wshadow \
-I../../../include -fno-common \
-mcpu=cortex-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F2
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = gpio.o rcc.o
OBJS += crc_common_all.o dac_common_all.o dma_common_f24.o \
gpio_common_all.o gpio_common_f0234.o i2c_common_all.o \
iwdg_common_all.o rtc_common_l1f024.o spi_common_all.o \
spi_common_f124.o timer_common_all.o timer_common_f234.o \
timer_common_f24.o usart_common_all.o usart_common_f124.o \
flash_common_f234.o flash_common_f24.o hash_common_f24.o \
crypto_common_f24.o exti_common_all.o
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include

View File

@ -0,0 +1,34 @@
/** @defgroup crc_file CRC
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx CRC</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crc.h>
#include <libopencm3/stm32/common/crc_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dac_file DAC
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx DAC</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dac.h>
#include <libopencm3/stm32/common/dac_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dma_file DMA
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx DMA</b>
@version 1.0.0
@date 30 November 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/common/dma_common_f24.h>

View File

@ -0,0 +1,31 @@
/** @defgroup gpio_file GPIO
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx General Purpose I/O</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/gpio.h>

View File

@ -0,0 +1,33 @@
/** @defgroup i2c_file I2C
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx I2C</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/stm32/common/spi_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup iwdg_file IWDG
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx Independent Watchdog Timer</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/iwdg.h>
#include <libopencm3/stm32/common/iwdg_common_all.h>

View File

@ -0,0 +1,106 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Generic linker script for STM32 targets using libopencm3. */
/* Memory regions must be defined in the ld script which includes this one. */
/* Enforce emmition of the vector table. */
EXTERN (vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
/* Define sections. */
SECTIONS
{
.text : {
*(.vectors) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >rom
/* C++ Static constructors/destructors, also used for __attribute__
* ((constructor)) and the likes */
.preinit_array : {
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
} >rom
.init_array : {
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} >rom
.fini_array : {
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
} >rom
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >rom
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >rom
. = ALIGN(4);
_etext = .;
.data : {
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
_edata = .;
} >ram AT >rom
_data_loadaddr = LOADADDR(.data);
.bss : {
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/DISCARD/ : { *(.eh_frame) }
. = ALIGN(4);
end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

View File

@ -0,0 +1,415 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/cm3/assert.h>
#include <libopencm3/stm32/f2/rcc.h>
#include <libopencm3/stm32/f2/flash.h>
/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */
uint32_t rcc_ppre1_frequency = 16000000;
uint32_t rcc_ppre2_frequency = 16000000;
const clock_scale_t hse_8mhz_3v3[CLOCK_3V3_END] = {
{ /* 120MHz */
.pllm = 8,
.plln = 240,
.pllp = 2,
.pllq = 5,
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE_DIV_4,
.ppre2 = RCC_CFGR_PPRE_DIV_2,
.flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE |
FLASH_ACR_LATENCY_3WS,
.apb1_frequency = 30000000,
.apb2_frequency = 60000000,
},
};
void rcc_osc_ready_int_clear(osc_t osc)
{
switch (osc) {
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYC;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYC;
break;
case HSI:
RCC_CIR |= RCC_CIR_HSIRDYC;
break;
case LSE:
RCC_CIR |= RCC_CIR_LSERDYC;
break;
case LSI:
RCC_CIR |= RCC_CIR_LSIRDYC;
break;
}
}
void rcc_osc_ready_int_enable(osc_t osc)
{
switch (osc) {
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYIE;
break;
case HSI:
RCC_CIR |= RCC_CIR_HSIRDYIE;
break;
case LSE:
RCC_CIR |= RCC_CIR_LSERDYIE;
break;
case LSI:
RCC_CIR |= RCC_CIR_LSIRDYIE;
break;
}
}
void rcc_osc_ready_int_disable(osc_t osc)
{
switch (osc) {
case PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYIE;
break;
case HSE:
RCC_CIR &= ~RCC_CIR_HSERDYIE;
break;
case HSI:
RCC_CIR &= ~RCC_CIR_HSIRDYIE;
break;
case LSE:
RCC_CIR &= ~RCC_CIR_LSERDYIE;
break;
case LSI:
RCC_CIR &= ~RCC_CIR_LSIRDYIE;
break;
}
}
int rcc_osc_ready_int_flag(osc_t osc)
{
switch (osc) {
case PLL:
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
break;
case HSE:
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
break;
case HSI:
return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
break;
case LSE:
return ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
break;
case LSI:
return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
break;
}
cm3_assert_not_reached();
}
void rcc_css_int_clear(void)
{
RCC_CIR |= RCC_CIR_CSSC;
}
int rcc_css_int_flag(void)
{
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
}
void rcc_wait_for_osc_ready(osc_t osc)
{
switch (osc) {
case PLL:
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
break;
case HSE:
while ((RCC_CR & RCC_CR_HSERDY) == 0);
break;
case HSI:
while ((RCC_CR & RCC_CR_HSIRDY) == 0);
break;
case LSE:
while ((RCC_BDCR & RCC_BDCR_LSERDY) == 0);
break;
case LSI:
while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
break;
}
}
void rcc_wait_for_sysclk_status(osc_t osc)
{
switch (osc) {
case PLL:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_PLL);
break;
case HSE:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSE);
break;
case HSI:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSI);
break;
default:
/* Shouldn't be reached. */
break;
}
}
void rcc_osc_on(osc_t osc)
{
switch (osc) {
case PLL:
RCC_CR |= RCC_CR_PLLON;
break;
case HSE:
RCC_CR |= RCC_CR_HSEON;
break;
case HSI:
RCC_CR |= RCC_CR_HSION;
break;
case LSE:
RCC_BDCR |= RCC_BDCR_LSEON;
break;
case LSI:
RCC_CSR |= RCC_CSR_LSION;
break;
}
}
void rcc_osc_off(osc_t osc)
{
switch (osc) {
case PLL:
RCC_CR &= ~RCC_CR_PLLON;
break;
case HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
case HSI:
RCC_CR &= ~RCC_CR_HSION;
break;
case LSE:
RCC_BDCR &= ~RCC_BDCR_LSEON;
break;
case LSI:
RCC_CSR &= ~RCC_CSR_LSION;
break;
}
}
void rcc_css_enable(void)
{
RCC_CR |= RCC_CR_CSSON;
}
void rcc_css_disable(void)
{
RCC_CR &= ~RCC_CR_CSSON;
}
void rcc_osc_bypass_enable(osc_t osc)
{
switch (osc) {
case HSE:
RCC_CR |= RCC_CR_HSEBYP;
break;
case LSE:
RCC_BDCR |= RCC_BDCR_LSEBYP;
break;
case PLL:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
break;
}
}
void rcc_osc_bypass_disable(osc_t osc)
{
switch (osc) {
case HSE:
RCC_CR &= ~RCC_CR_HSEBYP;
break;
case LSE:
RCC_BDCR &= ~RCC_BDCR_LSEBYP;
break;
case PLL:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
break;
}
}
void rcc_peripheral_enable_clock(volatile uint32_t *reg, uint32_t en)
{
*reg |= en;
}
void rcc_peripheral_disable_clock(volatile uint32_t *reg, uint32_t en)
{
*reg &= ~en;
}
void rcc_peripheral_reset(volatile uint32_t *reg, uint32_t reset)
{
*reg |= reset;
}
void rcc_peripheral_clear_reset(volatile uint32_t *reg, uint32_t clear_reset)
{
*reg &= ~clear_reset;
}
void rcc_set_sysclk_source(uint32_t clk)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 1) | (1 << 0));
RCC_CFGR = (reg32 | clk);
}
void rcc_set_pll_source(uint32_t pllsrc)
{
uint32_t reg32;
reg32 = RCC_PLLCFGR;
reg32 &= ~(1 << 22);
RCC_PLLCFGR = (reg32 | (pllsrc << 22));
}
void rcc_set_ppre2(uint32_t ppre2)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 13) | (1 << 14) | (1 << 15));
RCC_CFGR = (reg32 | (ppre2 << 13));
}
void rcc_set_ppre1(uint32_t ppre1)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 10) | (1 << 11) | (1 << 12));
RCC_CFGR = (reg32 | (ppre1 << 10));
}
void rcc_set_hpre(uint32_t hpre)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
RCC_CFGR = (reg32 | (hpre << 4));
}
void rcc_set_rtcpre(uint32_t rtcpre)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20));
RCC_CFGR = (reg32 | (rtcpre << 16));
}
void rcc_set_main_pll_hsi(uint32_t pllm, uint32_t plln, uint32_t pllp,
uint32_t pllq)
{
RCC_PLLCFGR = (pllm << RCC_PLLCFGR_PLLM_SHIFT) |
(plln << RCC_PLLCFGR_PLLN_SHIFT) |
(((pllp >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT) |
(pllq << RCC_PLLCFGR_PLLQ_SHIFT);
}
void rcc_set_main_pll_hse(uint32_t pllm, uint32_t plln, uint32_t pllp,
uint32_t pllq)
{
RCC_PLLCFGR = (pllm << RCC_PLLCFGR_PLLM_SHIFT) |
(plln << RCC_PLLCFGR_PLLN_SHIFT) |
(((pllp >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT) |
RCC_PLLCFGR_PLLSRC |
(pllq << RCC_PLLCFGR_PLLQ_SHIFT);
}
uint32_t rcc_system_clock_source(void)
{
/* Return the clock source which is used as system clock. */
return (RCC_CFGR & 0x000c) >> 2;
}
void rcc_clock_setup_hse_3v3(const clock_scale_t *clock)
{
/* Enable internal high-speed oscillator. */
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
/* Select HSI as SYSCLK source. */
rcc_set_sysclk_source(RCC_CFGR_SW_HSI);
/* Enable external high-speed oscillator 8MHz. */
rcc_osc_on(HSE);
rcc_wait_for_osc_ready(HSE);
/*
* Set prescalers for AHB, ADC, ABP1, ABP2.
* Do this before touching the PLL (TODO: why?).
*/
rcc_set_hpre(clock->hpre);
rcc_set_ppre1(clock->ppre1);
rcc_set_ppre2(clock->ppre2);
rcc_set_main_pll_hse(clock->pllm, clock->plln,
clock->pllp, clock->pllq);
/* Enable PLL oscillator and wait for it to stabilize. */
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
/* Configure flash settings. */
flash_set_ws(clock->flash_config);
/* Select PLL as SYSCLK source. */
rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
/* Wait for PLL clock to be selected. */
rcc_wait_for_sysclk_status(PLL);
/* Set the peripheral clock frequencies used. */
rcc_ppre1_frequency = clock->apb1_frequency;
rcc_ppre2_frequency = clock->apb2_frequency;
}
void rcc_backupdomain_reset(void)
{
/* Set the backup domain software reset. */
RCC_BDCR |= RCC_BDCR_BDRST;
/* Clear the backup domain software reset. */
RCC_BDCR &= ~RCC_BDCR_BDRST;
}

View File

@ -0,0 +1,32 @@
/** @defgroup rtc_file RTC
*
* @ingroup STM32F2xx
*
* @brief <b>libopencm3 STM32F2xx RTC</b>
*
* @version 1.0.0
*
* @date 4 March 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/rtc.h>
#include <libopencm3/stm32/common/rtc_common_l1f024.h>

View File

@ -0,0 +1,33 @@
/** @defgroup spi_file SPI
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx SPI</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/common/spi_common_f24.h>

View File

@ -0,0 +1,40 @@
/* This file is used for documentation purposes. It does not need
to be compiled. All source code is in the common area.
If there is any device specific code required it can be included here,
in which case this file must be added to the compile list. */
/** @defgroup timer_file Timers
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx Timers</b>
@version 1.0.0
@date 18 August 2012
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/common/timer_common_f24.h>

View File

@ -0,0 +1,33 @@
/** @defgroup usart_file USART
@ingroup STM32F2xx
@brief <b>libopencm3 STM32F2xx USART</b>
@version 1.0.0
@date 30 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/common/usart_common_all.h>

View File

@ -0,0 +1,49 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32f3
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
PREFIX ?= arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g \
-Wall -Wextra -Wimplicit-function-declaration \
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wshadow \
-I../../../include -fno-common \
-mcpu=cortex-m4 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F3
ARFLAGS = rcs
OBJS = rcc.o gpio.o adc.o i2c.o spi.o usart.o dma.o
OBJS += gpio_common_all.o gpio_common_f0234.o \
dac_common_all.o usart_common_all.o crc_common_all.o\
iwdg_common_all.o spi_common_all.o dma_common_l1f013.o\
timer_common_all.o timer_common_f234.o flash_common_f234.o \
flash.o exti_common_all.o
OBJS += usb.o usb_control.o usb_standard.o usb_f103.o
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
/** @defgroup crc_file CRC
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx CRC</b>
*
* @version 1.0.0
*
* @date 15 October 2012
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crc.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dac_file DAC
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx DAC</b>
*
* @version 1.0.0
*
* @date 18 August 2012
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dac.h>
#include <libopencm3/stm32/common/dac_common_all.h>

View File

@ -0,0 +1,33 @@
/** @defgroup dma_file DMA
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx Direct Memory Access</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/common/dma_common_l1f013.h>

View File

@ -0,0 +1,40 @@
/** @defgroup flash_file FLASH
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx FLASH</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/flash.h>
void flash_clear_status_flags(void)
{
flash_clear_pgperr_flag();
flash_clear_eop_flag();
flash_clear_bsy_flag();
}

View File

@ -0,0 +1,166 @@
/** @defgroup gpio_file GPIO
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx General Purpose I/O</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
* Modified by 2013 Fernando Cortes <fernando.corcam@gmail.com> (stm32f3)
* Modified by 2013 Guillermo Rivera <memogrg@gmail.com> (stm32f3)
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f3/gpio.h>
void gpio_mode_setup(uint32_t gpioport, uint8_t mode, uint8_t pull_up_down,
uint16_t gpios)
{
uint16_t i;
uint32_t moder, pupd;
/*
* We want to set the config only for the pins mentioned in gpios,
* but keeping the others, so read out the actual config first.
*/
moder = GPIO_MODER(gpioport);
pupd = GPIO_PUPDR(gpioport);
for (i = 0; i < 16; i++) {
if (!((1 << i) & gpios)) {
continue;
}
moder &= ~GPIO_MODE_MASK(i);
moder |= GPIO_MODE(i, mode);
pupd &= ~GPIO_PUPD_MASK(i);
pupd |= GPIO_PUPD(i, pull_up_down);
}
/* Set mode and pull up/down control registers. */
GPIO_MODER(gpioport) = moder;
GPIO_PUPDR(gpioport) = pupd;
}
void gpio_set_output_options(uint32_t gpioport, uint8_t otype, uint8_t speed,
uint16_t gpios)
{
uint16_t i;
uint32_t ospeedr;
if (otype == 0x1) {
GPIO_OTYPER(gpioport) |= gpios;
} else {
GPIO_OTYPER(gpioport) &= ~gpios;
}
ospeedr = GPIO_OSPEEDR(gpioport);
for (i = 0; i < 16; i++) {
if (!((1 << i) & gpios)) {
continue;
}
ospeedr &= ~GPIO_OSPEED_MASK(i);
ospeedr |= GPIO_OSPEED(i, speed);
}
GPIO_OSPEEDR(gpioport) = ospeedr;
}
void gpio_set_af(uint32_t gpioport, uint8_t alt_func_num, uint16_t gpios)
{
uint16_t i;
uint32_t afrl, afrh;
afrl = GPIO_AFRL(gpioport);
afrh = GPIO_AFRH(gpioport);
for (i = 0; i < 8; i++) {
if (!((1 << i) & gpios)) {
continue;
}
afrl &= ~GPIO_AFR_MASK(i);
afrl |= GPIO_AFR(i, alt_func_num);
}
for (i = 8; i < 16; i++) {
if (!((1 << i) & gpios)) {
continue;
}
afrl &= ~GPIO_AFR_MASK(i - 8);
afrh |= GPIO_AFR(i - 8, alt_func_num);
}
GPIO_AFRL(gpioport) = afrl;
GPIO_AFRH(gpioport) = afrh;
}
void gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
}
void gpio_clear(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios << 16;
}
uint16_t gpio_get(uint32_t gpioport, uint16_t gpios)
{
return gpio_port_read(gpioport) & gpios;
}
void gpio_toggle(uint32_t gpioport, uint16_t gpios)
{
GPIO_ODR(gpioport) ^= gpios;
}
uint16_t gpio_port_read(uint32_t gpioport)
{
return (uint16_t)GPIO_IDR(gpioport);
}
void gpio_port_write(uint32_t gpioport, uint16_t data)
{
GPIO_ODR(gpioport) = data;
}
void gpio_port_config_lock(uint32_t gpioport, uint16_t gpios)
{
uint32_t reg32;
/* Special "Lock Key Writing Sequence", see datasheet. */
GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
/*
* Tell the compiler the variable is actually used.
* It will get optimized out anyways.
*/
reg32 = reg32;
/* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
}

View File

@ -0,0 +1,486 @@
/** @defgroup i2c_file I2C
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx I2C</b>
*
* @version 1.0.0
*
* @date 15 October 2012
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/stm32/rcc.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief I2C Reset.
*
* The I2C peripheral and all its associated configuration registers are placed
* in the reset condition. The reset is effected via the RCC peripheral reset
* system.
*
* @param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base.
*/
void i2c_reset(uint32_t i2c)
{
switch (i2c) {
case I2C1:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
break;
case I2C2:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Peripheral Enable.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_peripheral_enable(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_PE;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Peripheral Disable.
*
* This must not be reset while in Master mode until a communication has
* finished. In Slave mode, the peripheral is disabled only after communication
* has ended.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_peripheral_disable(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_PE;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send Start Condition.
*
* If in Master mode this will cause a restart condition to occur at the end of
* the current transmission. If in Slave mode, this will initiate a start
* condition when the current bus activity is completed.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_send_start(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_START;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send Stop Condition.
*
* After the current byte transfer this will initiate a stop condition if in
* Master mode, or simply release the bus if in Slave mode.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_send_stop(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_STOP;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Clear Stop Flag.
*
* Clear the "Send Stop" flag in the I2C config register
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_clear_stop(uint32_t i2c)
{
I2C_ICR(i2c) |= I2C_ICR_STOPCF;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
*
* This sets an address for Slave mode operation, in 7 bit form.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
* @param[in] slave Unsigned int8. Slave address 0...127.
*/
void i2c_set_own_7bit_slave_address(uint32_t i2c, uint8_t slave)
{
I2C_OAR1(i2c) = (uint16_t)(slave << 1);
I2C_OAR1(i2c) &= ~I2C_OAR1_OA1MODE;
I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Set the 10 bit Slave Address for the Peripheral.
*
* This sets an address for Slave mode operation, in 10 bit form.
*
* @todo add "I2C_OAR1(i2c) |= (1 << 14);" as above
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
* @param[in] slave Unsigned int16. Slave address 0...1023.
*/
void i2c_set_own_10bit_slave_address(uint32_t i2c, uint16_t slave)
{
I2C_OAR1(i2c) = (uint16_t)(I2C_OAR1_OA1MODE | slave);
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Send Data.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
* @param[in] data Unsigned int8. Byte to send.
*/
void i2c_send_data(uint32_t i2c, uint8_t data)
{
I2C_TXDR(i2c) = data;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Get Data.
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
uint8_t i2c_get_data(uint32_t i2c)
{
return I2C_RXDR(i2c) & 0xff;
}
void i2c_enable_analog_filter(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_ANFOFF;
}
void i2c_disable_analog_filter(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_ANFOFF;
}
void i2c_set_digital_filter(uint32_t i2c, uint8_t dnf_setting)
{
I2C_CR1(i2c) = (I2C_CR1(i2c) & ~I2C_CR1_DNF_MASK) | dnf_setting;
}
/* t_presc= (presc+1)*t_i2cclk */
void i2c_set_prescaler(uint32_t i2c, uint8_t presc)
{
I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_PRESC_MASK) |
(presc << I2C_TIMINGR_PRESC_SHIFT);
}
void i2c_set_data_setup_time(uint32_t i2c, uint8_t s_time)
{
I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SCLDEL_MASK) |
(s_time << I2C_TIMINGR_SCLDEL_SHIFT);
}
void i2c_set_data_hold_time(uint32_t i2c, uint8_t h_time)
{
I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SDADEL_MASK) |
(h_time << I2C_TIMINGR_SDADEL_SHIFT);
}
void i2c_set_scl_high_period(uint32_t i2c, uint8_t period)
{
I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SCLH_MASK) |
(period << I2C_TIMINGR_SCLH_SHIFT);
}
void i2c_set_scl_low_period(uint32_t i2c, uint8_t period)
{
I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SCLL_MASK) |
(period << I2C_TIMINGR_SCLL_SHIFT);
}
void i2c_enable_stretching(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_NOSTRETCH;
}
void i2c_disable_stretching(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_NOSTRETCH;
}
void i2c_100khz_i2cclk8mhz(uint32_t i2c)
{
i2c_set_prescaler(i2c, 1);
i2c_set_scl_low_period(i2c, 0x13);
i2c_set_scl_high_period(i2c, 0xF);
i2c_set_data_hold_time(i2c, 0x2);
i2c_set_data_setup_time(i2c, 0x4);
}
void i2c_set_7bit_addr_mode(uint32_t i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_ADD10;
}
void i2c_set_10bit_addr_mode(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_ADD10;
}
void i2c_set_7bit_address(uint32_t i2c, uint8_t addr)
{
I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_SADD_7BIT_MASK) |
((addr & 0x7F) << I2C_CR2_SADD_7BIT_SHIFT);
}
void i2c_set_10bit_address(uint32_t i2c, uint16_t addr)
{
I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_SADD_10BIT_MASK) |
((addr & 0x3FF) << I2C_CR2_SADD_10BIT_SHIFT);
}
void i2c_set_write_transfer_dir(uint32_t i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_RD_WRN;
}
void i2c_set_read_transfer_dir(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_RD_WRN;
}
void i2c_set_bytes_to_transfer(uint32_t i2c, uint32_t n_bytes)
{
I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_NBYTES_MASK) |
(n_bytes << I2C_CR2_NBYTES_SHIFT);
}
uint8_t i2c_is_start(uint32_t i2c)
{
if ((I2C_CR2(i2c) & I2C_CR2_START) != 0) {
return 1;
}
return 0;
}
void i2c_enable_autoend(uint32_t i2c)
{
I2C_CR2(i2c) |= I2C_CR2_AUTOEND;
}
void i2c_disable_autoend(uint32_t i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_AUTOEND;
}
uint8_t i2c_nack(uint32_t i2c)
{
if ((I2C_ISR(i2c) & I2C_ISR_NACKF) != 0) {
return 1;
}
return 0;
}
uint8_t i2c_busy(uint32_t i2c)
{
if ((I2C_ISR(i2c) & I2C_ISR_BUSY) != 0) {
return 1;
}
return 0;
}
uint8_t i2c_transmit_int_status(uint32_t i2c)
{
if ((I2C_ISR(i2c) & I2C_ISR_TXIS) != 0) {
return 1;
}
return 0;
}
uint8_t i2c_transfer_complete(uint32_t i2c)
{
if ((I2C_ISR(i2c) & I2C_ISR_TC) != 0) {
return 1;
}
return 0;
}
uint8_t i2c_received_data(uint32_t i2c)
{
if ((I2C_ISR(i2c) & I2C_ISR_RXNE) != 0) {
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Enable Interrupt
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
* @param[in] interrupt Unsigned int32. Interrupt to enable.
*/
void i2c_enable_interrupt(uint32_t i2c, uint32_t interrupt)
{
I2C_CR1(i2c) |= interrupt;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Disable Interrupt
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
* @param[in] interrupt Unsigned int32. Interrupt to disable.
*/
void i2c_disable_interrupt(uint32_t i2c, uint32_t interrupt)
{
I2C_CR1(i2c) &= ~interrupt;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Enable reception DMA
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_rxdma(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_RXDMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Disable reception DMA
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_rxdma(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_RXDMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Enable transmission DMA
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_txdma(uint32_t i2c)
{
I2C_CR1(i2c) |= I2C_CR1_TXDMAEN;
}
/*---------------------------------------------------------------------------*/
/** @brief I2C Disable transmission DMA
*
* @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_txdma(uint32_t i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_TXDMAEN;
}
void write_i2c(uint32_t i2c, uint8_t i2c_addr, uint8_t reg, uint8_t size,
uint8_t *data)
{
int wait;
int i;
while (i2c_busy(i2c) == 1);
while (i2c_is_start(i2c) == 1);
/*Setting transfer properties*/
i2c_set_bytes_to_transfer(i2c, size + 1);
i2c_set_7bit_address(i2c, (i2c_addr & 0x7F));
i2c_set_write_transfer_dir(i2c);
i2c_enable_autoend(i2c);
/*start transfer*/
i2c_send_start(i2c);
wait = true;
while (wait) {
if (i2c_transmit_int_status(i2c)) {
wait = false;
}
while (i2c_nack(i2c));
}
i2c_send_data(i2c, reg);
for (i = 0; i < size; i++) {
wait = true;
while (wait) {
if (i2c_transmit_int_status(i2c)) {
wait = false;
}
while (i2c_nack(i2c));
}
i2c_send_data(i2c, data[i]);
}
}
void read_i2c(uint32_t i2c, uint8_t i2c_addr, uint8_t reg, uint8_t size,
uint8_t *data)
{
int wait;
int i;
while (i2c_busy(i2c) == 1);
while (i2c_is_start(i2c) == 1);
/*Setting transfer properties*/
i2c_set_bytes_to_transfer(i2c, 1);
i2c_set_7bit_address(i2c, i2c_addr);
i2c_set_write_transfer_dir(i2c);
i2c_disable_autoend(i2c);
/*start transfer*/
i2c_send_start(i2c);
wait = true;
while (wait) {
if (i2c_transmit_int_status(i2c)) {
wait = false;
}
while (i2c_nack(i2c)); /* Some error */
}
i2c_send_data(i2c, reg);
while (i2c_is_start(i2c) == 1);
/*Setting transfer properties*/
i2c_set_bytes_to_transfer(i2c, size);
i2c_set_7bit_address(i2c, i2c_addr);
i2c_set_read_transfer_dir(i2c);
i2c_enable_autoend(i2c);
/*start transfer*/
i2c_send_start(i2c);
for (i = 0; i < size; i++) {
while (i2c_received_data(i2c) == 0);
data[i] = i2c_get_data(i2c);
}
}
/**@}*/

View File

@ -0,0 +1,33 @@
/** @defgroup iwdg_file IWDG
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx Independent Watchdog Timer</b>
*
* @version 1.0.0
*
* @date 18 August 2012
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/iwdg.h>
#include <libopencm3/stm32/common/iwdg_common_all.h>

View File

@ -0,0 +1,106 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Generic linker script for STM32 targets using libopencm3. */
/* Memory regions must be defined in the ld script which includes this one. */
/* Enforce emmition of the vector table. */
EXTERN (vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
/* Define sections. */
SECTIONS
{
.text : {
*(.vectors) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >rom
/* C++ Static constructors/destructors, also used for __attribute__
* ((constructor)) and the likes */
.preinit_array : {
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
} >rom
.init_array : {
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} >rom
.fini_array : {
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
} >rom
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >rom
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >rom
. = ALIGN(4);
_etext = .;
.data : {
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
_edata = .;
} >ram AT >rom
_data_loadaddr = LOADADDR(.data);
.bss : {
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/DISCARD/ : { *(.eh_frame) }
. = ALIGN(4);
end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

View File

@ -0,0 +1,33 @@
/** @defgroup pwr_file PWR
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx Power control</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/pwr.h>

View File

@ -0,0 +1,482 @@
/** @defgroup rcc_file RCC
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx Reset and Clock Control</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Modified by 2013 Fernando Cortes <fernando.corcam@gmail.com> (stm32f3)
* Modified by 2013 Guillermo Rivera <memogrg@gmail.com> (stm32f3)
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/cm3/assert.h>
#include <libopencm3/stm32/f3/rcc.h>
#include <libopencm3/stm32/f3/flash.h>
#include <libopencm3/stm32/f3/i2c.h>
/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */
uint32_t rcc_ppre1_frequency = 8000000;
uint32_t rcc_ppre2_frequency = 8000000;
const clock_scale_t hsi_8mhz[CLOCK_END] = {
{ /* 44MHz */
.pll = RCC_CFGR_PLLMUL_PLL_IN_CLK_X11,
.pllsrc = RCC_CFGR_PLLSRC_HSI_DIV2,
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE1_DIV_2,
.ppre2 = RCC_CFGR_PPRE2_DIV_NONE,
.power_save = 1,
.flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1WS,
.apb1_frequency = 22000000,
.apb2_frequency = 44000000,
},
{ /* 48MHz */
.pll = RCC_CFGR_PLLMUL_PLL_IN_CLK_X12,
.pllsrc = RCC_CFGR_PLLSRC_HSI_DIV2,
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE1_DIV_2,
.ppre2 = RCC_CFGR_PPRE2_DIV_NONE,
.power_save = 1,
.flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1WS,
.apb1_frequency = 24000000,
.apb2_frequency = 48000000,
},
{ /* 64MHz */
.pll = RCC_CFGR_PLLMUL_PLL_IN_CLK_X16,
.pllsrc = RCC_CFGR_PLLSRC_HSI_DIV2,
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE1_DIV_2,
.ppre2 = RCC_CFGR_PPRE2_DIV_NONE,
.power_save = 1,
.flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2WS,
.apb1_frequency = 32000000,
.apb2_frequency = 64000000,
}
};
void rcc_osc_ready_int_clear(enum osc osc)
{
switch (osc) {
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYC;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYC;
break;
case HSI:
RCC_CIR |= RCC_CIR_HSIRDYC;
break;
case LSE:
RCC_CIR |= RCC_CIR_LSERDYC;
break;
case LSI:
RCC_CIR |= RCC_CIR_LSIRDYC;
break;
}
}
void rcc_osc_ready_int_enable(enum osc osc)
{
switch (osc) {
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYIE;
break;
case HSI:
RCC_CIR |= RCC_CIR_HSIRDYIE;
break;
case LSE:
RCC_CIR |= RCC_CIR_LSERDYIE;
break;
case LSI:
RCC_CIR |= RCC_CIR_LSIRDYIE;
break;
}
}
void rcc_osc_ready_int_disable(enum osc osc)
{
switch (osc) {
case PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYIE;
break;
case HSE:
RCC_CIR &= ~RCC_CIR_HSERDYIE;
break;
case HSI:
RCC_CIR &= ~RCC_CIR_HSIRDYIE;
break;
case LSE:
RCC_CIR &= ~RCC_CIR_LSERDYIE;
break;
case LSI:
RCC_CIR &= ~RCC_CIR_LSIRDYIE;
break;
}
}
int rcc_osc_ready_int_flag(enum osc osc)
{
switch (osc) {
case PLL:
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
break;
case HSE:
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
break;
case HSI:
return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
break;
case LSE:
return ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
break;
case LSI:
return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
break;
}
cm3_assert_not_reached();
}
void rcc_css_int_clear(void)
{
RCC_CIR |= RCC_CIR_CSSC;
}
int rcc_css_int_flag(void)
{
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
}
void rcc_wait_for_osc_ready(enum osc osc)
{
switch (osc) {
case PLL:
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
break;
case HSE:
while ((RCC_CR & RCC_CR_HSERDY) == 0);
break;
case HSI:
while ((RCC_CR & RCC_CR_HSIRDY) == 0);
break;
case LSE:
while ((RCC_BDCR & RCC_BDCR_LSERDY) == 0);
break;
case LSI:
while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
break;
}
}
void rcc_wait_for_osc_not_ready(enum osc osc)
{
switch (osc) {
case PLL:
while ((RCC_CR & RCC_CR_PLLRDY) != 0);
break;
case HSE:
while ((RCC_CR & RCC_CR_HSERDY) != 0);
break;
case HSI:
while ((RCC_CR & RCC_CR_HSIRDY) != 0);
break;
case LSE:
while ((RCC_BDCR & RCC_BDCR_LSERDY) != 0);
break;
case LSI:
while ((RCC_CSR & RCC_CSR_LSIRDY) != 0);
break;
}
}
void rcc_wait_for_sysclk_status(enum osc osc)
{
switch (osc) {
case PLL:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_PLL);
break;
case HSE:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSE);
break;
case HSI:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSI);
break;
default:
/* Shouldn't be reached. */
break;
}
}
void rcc_osc_on(enum osc osc)
{
switch (osc) {
case PLL:
RCC_CR |= RCC_CR_PLLON;
break;
case HSE:
RCC_CR |= RCC_CR_HSEON;
break;
case HSI:
RCC_CR |= RCC_CR_HSION;
break;
case LSE:
RCC_BDCR |= RCC_BDCR_LSEON;
break;
case LSI:
RCC_CSR |= RCC_CSR_LSION;
break;
}
}
void rcc_osc_off(enum osc osc)
{
switch (osc) {
case PLL:
RCC_CR &= ~RCC_CR_PLLON;
break;
case HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
case HSI:
RCC_CR &= ~RCC_CR_HSION;
break;
case LSE:
RCC_BDCR &= ~RCC_BDCR_LSEON;
break;
case LSI:
RCC_CSR &= ~RCC_CSR_LSION;
break;
}
}
void rcc_css_enable(void)
{
RCC_CR |= RCC_CR_CSSON;
}
void rcc_css_disable(void)
{
RCC_CR &= ~RCC_CR_CSSON;
}
void rcc_osc_bypass_enable(enum osc osc)
{
switch (osc) {
case HSE:
RCC_CR |= RCC_CR_HSEBYP;
break;
case LSE:
RCC_BDCR |= RCC_BDCR_LSEBYP;
break;
case PLL:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
break;
}
}
void rcc_osc_bypass_disable(enum osc osc)
{
switch (osc) {
case HSE:
RCC_CR &= ~RCC_CR_HSEBYP;
break;
case LSE:
RCC_BDCR &= ~RCC_BDCR_LSEBYP;
break;
case PLL:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
break;
}
}
void rcc_peripheral_enable_clock(volatile uint32_t *reg, uint32_t en)
{
*reg |= en;
}
void rcc_peripheral_disable_clock(volatile uint32_t *reg, uint32_t en)
{
*reg &= ~en;
}
void rcc_peripheral_reset(volatile uint32_t *reg, uint32_t reset)
{
*reg |= reset;
}
void rcc_peripheral_clear_reset(volatile uint32_t *reg, uint32_t clear_reset)
{
*reg &= ~clear_reset;
}
void rcc_set_sysclk_source(uint32_t clk)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 1) | (1 << 0));
RCC_CFGR = (reg32 | clk);
}
void rcc_set_pll_source(uint32_t pllsrc)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~RCC_CFGR_PLLSRC;
RCC_CFGR = (reg32 | (pllsrc << 16));
}
void rcc_set_ppre2(uint32_t ppre2)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 13) | (1 << 14) | (1 << 15));
RCC_CFGR = (reg32 | (ppre2 << 11));
}
void rcc_set_ppre1(uint32_t ppre1)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 10) | (1 << 11) | (1 << 12));
RCC_CFGR = (reg32 | (ppre1 << 8));
}
void rcc_set_hpre(uint32_t hpre)
{
uint32_t reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
RCC_CFGR = (reg32 | (hpre << 4));
}
void rcc_set_main_pll_hsi(uint32_t pll)
{
RCC_CFGR = (~RCC_CFGR_PLLMUL_MASK & RCC_CFGR) |
(pll << RCC_CFGR_PLLMUL_SHIFT);
}
uint32_t rcc_get_system_clock_source(void)
{
/* Return the clock source which is used as system clock. */
return (RCC_CFGR & 0x000c) >> 2;
}
void rcc_clock_setup_hsi(const clock_scale_t *clock)
{
/* Enable internal high-speed oscillator. */
rcc_osc_on(HSI);
rcc_wait_for_osc_ready(HSI);
/* Select HSI as SYSCLK source. */
rcc_set_sysclk_source(RCC_CFGR_SW_HSI); /* XXX: se cayo */
rcc_wait_for_sysclk_status(HSI);
rcc_osc_off(PLL);
rcc_wait_for_osc_not_ready(PLL);
rcc_set_pll_source(clock->pllsrc);
rcc_set_main_pll_hsi(clock->pll);
/* Enable PLL oscillator and wait for it to stabilize. */
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
/*
* Set prescalers for AHB, ADC, ABP1, ABP2.
* Do this before touching the PLL (TODO: why?).
*/
rcc_set_hpre(clock->hpre);
rcc_set_ppre2(clock->ppre2);
rcc_set_ppre1(clock->ppre1);
/* Configure flash settings. */
flash_set_ws(clock->flash_config);
/* Select PLL as SYSCLK source. */
rcc_set_sysclk_source(RCC_CFGR_SW_PLL); /* XXX: se cayo */
/* Wait for PLL clock to be selected. */
rcc_wait_for_sysclk_status(PLL);
/* Set the peripheral clock frequencies used. */
rcc_ppre1_frequency = clock->apb1_frequency;
rcc_ppre2_frequency = clock->apb2_frequency;
}
void rcc_backupdomain_reset(void)
{
/* Set the backup domain software reset. */
RCC_BDCR |= RCC_BDCR_BDRST;
/* Clear the backup domain software reset. */
RCC_BDCR &= ~RCC_BDCR_BDRST;
}
void rcc_set_i2c_clock_hsi(uint32_t i2c)
{
if (i2c == I2C1) {
RCC_CFGR3 &= ~RCC_CFGR3_I2C1SW;
}
if (i2c == I2C2) {
RCC_CFGR3 &= ~RCC_CFGR3_I2C2SW;
}
}
void rcc_set_i2c_clock_sysclk(uint32_t i2c)
{
if (i2c == I2C1) {
RCC_CFGR3 |= RCC_CFGR3_I2C1SW;
}
if (i2c == I2C2) {
RCC_CFGR3 |= RCC_CFGR3_I2C2SW;
}
}
uint32_t rcc_get_i2c_clocks(void)
{
return RCC_CFGR3 & (RCC_CFGR3_I2C1SW | RCC_CFGR3_I2C2SW);
}
void rcc_usb_prescale_1_5(void)
{
RCC_CFGR &= ~RCC_CFGR_USBPRES;
}
void rcc_usb_prescale_1(void)
{
RCC_CFGR |= RCC_CFGR_USBPRES;
}

View File

@ -0,0 +1,72 @@
/** @defgroup spi_file SPI
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx Serial Peripheral Interface</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/rcc.h>
void spi_send8(uint32_t spi, uint8_t data)
{
/* Wait for transfer finished. */
while (!(SPI_SR(spi) & SPI_SR_TXE));
/* Write data (8 or 16 bits, depending on DFF) into DR. */
SPI_DR8(spi) = data;
}
uint8_t spi_read8(uint32_t spi)
{
/* Wait for transfer finished. */
while (!(SPI_SR(spi) & SPI_SR_RXNE));
/* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
return SPI_DR8(spi);
}
void spi_set_data_size(uint32_t spi, uint16_t data_s)
{
SPI_CR2(spi) = (SPI_CR2(spi) & ~SPI_CR2_DS_MASK) |
(data_s & SPI_CR2_DS_MASK);
}
void spi_fifo_reception_threshold_8bit(uint32_t spi)
{
SPI_CR2(spi) |= SPI_CR2_FRXTH;
}
void spi_fifo_reception_threshold_16bit(uint32_t spi)
{
SPI_CR2(spi) &= ~SPI_CR2_FRXTH;
}
void spi_i2s_mode_spi_mode(uint32_t spi)
{
SPI_I2SCFGR(spi) &= ~SPI_I2SCFGR_I2SMOD;
}

View File

@ -0,0 +1,33 @@
/** @defgroup timer_file TIMER
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx Timers</b>
*
* @version 1.0.0
*
* @date 11 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/timer.h>

View File

@ -0,0 +1,141 @@
/** @defgroup usart_file USART
*
* @ingroup STM32F3xx
*
* @brief <b>libopencm3 STM32F3xx USART</b>
*
* @version 1.0.0
*
* @date 30 August 2012
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/common/usart_common_all.h>
/*---------------------------------------------------------------------------*/
/** @brief USART Send a Data Word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] data unsigned 16 bit.
*/
void usart_send(uint32_t usart, uint16_t data)
{
/* Send data. */
USART_TDR(usart) = (data & USART_TDR_MASK);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word.
*
* If parity is enabled the MSB (bit 7 or 8 depending on the word length) is
* the parity bit.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @returns unsigned 16 bit data word.
*/
uint16_t usart_recv(uint32_t usart)
{
/* Receive data. */
return USART_RDR(usart) & USART_RDR_MASK;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Wait for Transmit Data Buffer Empty
*
* Blocks until the transmit data buffer becomes empty and is ready to accept
* the next data word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_wait_send_ready(uint32_t usart)
{
/* Wait until the data has been transferred into the shift register. */
while ((USART_ISR(usart) & USART_ISR_TXE) == 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Wait for Received Data Available
*
* Blocks until the receive data buffer holds a valid received data word.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
*/
void usart_wait_recv_ready(uint32_t usart)
{
/* Wait until the data is ready to be received. */
while ((USART_ISR(usart) & USART_ISR_RXNE) == 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Status Flag.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
* @returns boolean: flag set.
*/
bool usart_get_flag(uint32_t usart, uint32_t flag)
{
return ((USART_ISR(usart) & flag) != 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Return Interrupt Source.
*
* Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was
* set and the interrupt was enabled. If the specified flag is not an interrupt
* flag, the function returns false.
*
* @todo These are the most important interrupts likely to be used. Others
* relating to LIN break, and error conditions in multibuffer communication,
* need to be added for completeness.
*
* @param[in] usart unsigned 32 bit. USART block register address base @ref
* usart_reg_base
* @param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
* @returns boolean: flag and interrupt enable both set.
*/
bool usart_get_interrupt_source(uint32_t usart, uint32_t flag)
{
uint32_t flag_set = (USART_ISR(usart) & flag);
/* IDLE, RXNE, TC, TXE interrupts */
if ((flag >= USART_ISR_IDLE) && (flag <= USART_ISR_TXE)) {
return ((flag_set & USART_CR1(usart)) != 0);
/* Overrun error */
} else if (flag == USART_ISR_ORE) {
return flag_set && (USART_CR3(usart) & USART_CR3_CTSIE);
}
return false;
}
/**@}*/

View File

@ -0,0 +1,27 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/cm3/scb.h>
static void pre_main(void)
{
/* Enable access to Floating-Point coprocessor. */
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
}

View File

@ -0,0 +1,54 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32f4
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
PREFIX ?= arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g \
-Wall -Wextra -Wimplicit-function-declaration \
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wshadow \
-I../../../include -fno-common \
-mcpu=cortex-m4 -mthumb $(FP_FLAGS) \
-Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F4
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = adc.o can.o gpio.o pwr.o rcc.o rtc.o crypto.o
OBJS += crc_common_all.o dac_common_all.o dma_common_f24.o \
gpio_common_all.o gpio_common_f0234.o i2c_common_all.o \
iwdg_common_all.o pwr_common_all.o rtc_common_l1f024.o \
spi_common_all.o spi_common_f124.o timer_common_all.o \
timer_common_f234.o timer_common_f24.o usart_common_all.o \
usart_common_f124.o flash_common_f234.o flash_common_f24.o \
hash_common_f24.o crypto_common_f24.o exti_common_all.o
OBJS += usb.o usb_standard.o usb_control.o usb_fx07_common.o \
usb_f107.o usb_f207.o
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
/** @defgroup crc_file CRC
@ingroup STM32F4xx
@brief <b>libopencm3 STM32F4xx CRC</b>
@version 1.0.0
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crc.h>
#include <libopencm3/stm32/common/crc_common_all.h>

View File

@ -0,0 +1,66 @@
/** @defgroup crypto_file CRYPTO
*
* @ingroup STM32F4xx
*
* @brief <b>libopencm3 STM32F4xx CRYPTO</b>
*
* @version 1.0.0
*
* @date 18 Jun 2013
*
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/crypto.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/** @brief Set the MAC algorithm
*/
void crypto_set_mac_algorithm(enum crypto_mode_mac mode)
{
crypto_set_algorithm((enum crypto_mode) mode);
}
/**
* @brief Swap context
*
*@param[in] buf uint32_t Memory space for swap (16 items length)
*/
void crypto_context_swap(uint32_t *buf)
{
int i;
/* Apply exact order of ? */
for (i = 0; i < 8; i++) {
uint32_t save = *buf;
*buf++ = CRYP_CSGCMCCMR(i);
CRYP_CSGCMCCMR(i) = save;
};
for (i = 0; i < 8; i++) {
uint32_t save = *buf;
*buf++ = CRYP_CSGCMR(i);
CRYP_CSGCMCCMR(i) = save;
};
}
/**@}*/

View File

@ -0,0 +1,33 @@
/** @defgroup dac_file DAC
@ingroup STM32F4xx
@brief <b>libopencm3 STM32F4xx DAC</b>
@version 1.0.0
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/dac.h>
#include <libopencm3/stm32/common/dac_common_all.h>

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