810 lines
28 KiB
C
810 lines
28 KiB
C
|
/** @addtogroup dma_file DMA peripheral API
|
||
|
@ingroup peripheral_apis
|
||
|
|
||
|
@author @htmlonly © @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 Get the Transfer Block Size
|
||
|
|
||
|
@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 int16. Number of remaining data words to transfer (65535
|
||
|
maximum).
|
||
|
*/
|
||
|
|
||
|
uint16_t dma_get_number_of_data(uint32_t dma, uint8_t stream)
|
||
|
{
|
||
|
return DMA_SNDTR(dma, stream);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
/** @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;
|
||
|
}
|
||
|
/**@}*/
|
||
|
|