This commit is contained in:
2025-06-18 09:08:17 +08:00
commit 7999439a8f
363 changed files with 313769 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2015 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 24. December 2015
* $Revision: V1.1
*
* Driver: Driver_CAN1/2
* Configured: via RTE_Device.h configuration file
* Project: CAN Driver Header for ST STM32F1xx
* -------------------------------------------------------------------------- */
#ifndef __CAN_STM32F1XX_H
#define __CAN_STM32F1XX_H
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "Driver_CAN.h"
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "RTE_Components.h"
#include "RTE_Device.h"
#if ((defined(RTE_Drivers_CAN1) || defined(RTE_Drivers_CAN2)) && \
((RTE_CAN1 == 0) && (RTE_CAN2 == 0)))
#error "No CAN configured in RTE_Device.h!"
#endif
#if (RTE_CAN1 != 0)
#define MX_CAN1 1
/* Pin CAN1_RX */
#define MX_CAN1_RX_Pin 1
#define MX_CAN1_RX_GPIOx RTE_CAN1_RX_PORT
#define MX_CAN1_RX_GPIO_Pin RTE_CAN1_RX_BIT
#if (RTE_CAN1_RX_PORT_ID == 0)
#define MX_CAN1_RX_GPIO_AF AFIO_CAN_PA11_PA12
#elif (RTE_CAN1_RX_PORT_ID == 1)
#define MX_CAN1_RX_GPIO_AF AFIO_CAN_PB8_PB9
#elif (RTE_CAN1_RX_PORT_ID == 2)
#define MX_CAN1_RX_GPIO_AF AFIO_CAN_PD0_PD1
#else
#error "Unknown alternate function for CAN1_RX pin!"
#endif
#define MX_CAN1_RX_GPIO_Conf GPIO_IN_FLOATING
#define MX_CAN1_RX_GPIO_Mode GPIO_MODE_INPUT
/* Pin CAN1_TX */
#define MX_CAN1_TX_Pin 1
#define MX_CAN1_TX_GPIOx RTE_CAN1_TX_PORT
#define MX_CAN1_TX_GPIO_Pin RTE_CAN1_TX_BIT
#if (RTE_CAN1_TX_PORT_ID == 0)
#define MX_CAN1_TX_GPIO_AF AFIO_CAN_PA11_PA12
#elif (RTE_CAN1_TX_PORT_ID == 1)
#define MX_CAN1_TX_GPIO_AF AFIO_CAN_PB8_PB9
#elif (RTE_CAN1_TX_PORT_ID == 2)
#define MX_CAN1_TX_GPIO_AF AFIO_CAN_PD0_PD1
#else
#error "Unknown alternate function for CAN1_TX pin!"
#endif
#define MX_CAN1_TX_GPIO_Conf GPIO_AF_PUSHPULL
#define MX_CAN1_TX_GPIO_Mode GPIO_MODE_OUT2MHZ
#endif
#if (RTE_CAN2 != 0)
#define MX_CAN2 1
/* Pin CAN2_RX */
#define MX_CAN2_RX_Pin 1
#define MX_CAN2_RX_GPIOx RTE_CAN2_RX_PORT
#define MX_CAN2_RX_GPIO_Pin RTE_CAN2_RX_BIT
#if (RTE_CAN2_RX_PORT_ID == 0)
#define MX_CAN2_RX_GPIO_AF AFIO_CAN2_REMAP
#elif (RTE_CAN2_RX_PORT_ID == 1)
#define MX_CAN2_RX_GPIO_AF AFIO_CAN2_NO_REMAP
#else
#error "Unknown alternate function for CAN2_RX pin!"
#endif
#define MX_CAN2_RX_GPIO_Conf GPIO_IN_FLOATING
#define MX_CAN2_RX_GPIO_Mode GPIO_MODE_INPUT
/* Pin CAN2_TX */
#define MX_CAN2_TX_Pin 1
#define MX_CAN2_TX_GPIOx RTE_CAN2_TX_PORT
#define MX_CAN2_TX_GPIO_Pin RTE_CAN2_TX_BIT
#if (RTE_CAN2_TX_PORT_ID == 0)
#define MX_CAN2_TX_GPIO_AF AFIO_CAN2_REMAP
#elif (RTE_CAN2_TX_PORT_ID == 1)
#define MX_CAN2_TX_GPIO_AF AFIO_CAN2_NO_REMAP
#else
#error "Unknown alternate function for CAN2_TX pin!"
#endif
#define MX_CAN2_TX_GPIO_Conf GPIO_AF_PUSHPULL
#define MX_CAN2_TX_GPIO_Mode GPIO_MODE_OUT2MHZ
#endif
#ifndef STM32F10X_CL
#define CAN1_TX_IRQn USB_HP_CAN1_TX_IRQn
#define CAN1_RX0_IRQn USB_LP_CAN1_RX0_IRQn
#endif
#if !defined(MX_CAN1)
#define MX_CAN1 (0U)
#endif
#if !defined(MX_CAN2)
#define MX_CAN2 (0U)
#endif
#if (MX_CAN2 == 1U)
#define CAN_CTRL_NUM (2U)
#else
#define CAN_CTRL_NUM (1U)
#endif
#endif // __CAN_STM32F1XX_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,472 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2015 ARM Limited. All rights reserved.
*
* $Date: 27. August 2013
* $Revision: V1.2
*
* Project: DMA Driver for ST STM32F10x
* -------------------------------------------------------------------- */
/* History:
* Version 1.2
* DMAx_Channel variable is checked for initialized channels in DMA_ChannelUninitialize function
* Version 1.1
* DMA2 peripheral added to build when HD, XL, HD_VL or CL device is used
* Version 1.0
* Initial release
*/
#include "DMA_STM32F10x.h"
#if defined(STM32F10X_HD) || defined(STM32F10X_XL) || \
defined(STM32F10X_HD_VL) || defined(STM32F10X_CL)
/* DMA2 peripheral exists on HD, XL, HD_VL and CL devices */
#define STM32F10X_ENABLE_DMA2
#endif
/// DMA Variables
static uint8_t DMA1_Channel; // Used DMA1 Channels
#if defined (STM32F10X_ENABLE_DMA2)
static uint8_t DMA2_Channel; // Used DMA2 Channels
#endif
/// DMA Functions
/**
\fn void DMA_ChannelInitialize (uint32_t dma, uint32_t channel)
\brief Initialize DMA Channel
\param[in] dma DMA number
\param[in] channel DMA channel number
*/
void DMA_ChannelInitialize (uint32_t dma, uint32_t channel) {
switch (dma) {
case 1:
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
switch (channel) {
case 1:
DMA1_Channel1->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTEIF1 |
DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1;
NVIC_ClearPendingIRQ(DMA1_Channel1_IRQn);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
break;
case 2:
DMA1_Channel2->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTEIF2 |
DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2;
NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
break;
case 3:
DMA1_Channel3->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTEIF3 |
DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3;
NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
NVIC_EnableIRQ(DMA1_Channel3_IRQn);
break;
case 4:
DMA1_Channel4->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTEIF4 |
DMA_IFCR_CHTIF4 | DMA_IFCR_CTCIF4;
NVIC_ClearPendingIRQ(DMA1_Channel4_IRQn);
NVIC_EnableIRQ(DMA1_Channel4_IRQn);
break;
case 5:
DMA1_Channel5->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTEIF5 |
DMA_IFCR_CHTIF5 | DMA_IFCR_CTCIF5;
NVIC_ClearPendingIRQ(DMA1_Channel5_IRQn);
NVIC_EnableIRQ(DMA1_Channel5_IRQn);
break;
case 6:
DMA1_Channel6->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF6 | DMA_IFCR_CTEIF6 |
DMA_IFCR_CHTIF6 | DMA_IFCR_CTCIF6;
NVIC_ClearPendingIRQ(DMA1_Channel6_IRQn);
NVIC_EnableIRQ(DMA1_Channel6_IRQn);
break;
case 7:
DMA1_Channel7->CCR = 0;
DMA1->IFCR = DMA_IFCR_CGIF7 | DMA_IFCR_CTEIF7 |
DMA_IFCR_CHTIF7 | DMA_IFCR_CTCIF7;
NVIC_ClearPendingIRQ(DMA1_Channel7_IRQn);
NVIC_EnableIRQ(DMA1_Channel7_IRQn);
break;
}
DMA1_Channel |= 1 << channel;
break;
#if defined (STM32F10X_ENABLE_DMA2)
case 2:
RCC->AHBENR |= RCC_AHBENR_DMA2EN;
switch (channel) {
case 1:
DMA2_Channel1->CCR = 0;
DMA2->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTEIF1 |
DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1;
NVIC_ClearPendingIRQ(DMA2_Channel1_IRQn);
NVIC_EnableIRQ(DMA2_Channel1_IRQn);
break;
case 2:
DMA2_Channel2->CCR = 0;
DMA2->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CTEIF2 |
DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2;
NVIC_ClearPendingIRQ(DMA2_Channel2_IRQn);
NVIC_EnableIRQ(DMA2_Channel2_IRQn);
break;
case 3:
DMA2_Channel3->CCR = 0;
DMA2->IFCR = DMA_IFCR_CGIF3 | DMA_IFCR_CTEIF3 |
DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3;
NVIC_ClearPendingIRQ(DMA2_Channel3_IRQn);
NVIC_EnableIRQ(DMA2_Channel3_IRQn);
break;
case 4:
DMA2_Channel4->CCR = 0;
DMA2->IFCR = DMA_IFCR_CGIF4 | DMA_IFCR_CTEIF4 |
DMA_IFCR_CHTIF4 | DMA_IFCR_CTCIF4;
#if defined (STM32F10X_CL)
NVIC_ClearPendingIRQ(DMA2_Channel4_IRQn);
NVIC_EnableIRQ(DMA2_Channel4_IRQn);
#else
NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn);
NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
#endif
break;
case 5:
DMA2_Channel5->CCR = 0;
DMA2->IFCR = DMA_IFCR_CGIF5 | DMA_IFCR_CTEIF5 |
DMA_IFCR_CHTIF5 | DMA_IFCR_CTCIF5;
#if defined (STM32F10X_CL)
NVIC_ClearPendingIRQ(DMA2_Channel5_IRQn);
NVIC_EnableIRQ(DMA2_Channel5_IRQn);
#elif defined (STM32F10X_HD_VL)
if (AFIO->MAPR2 & AFIO_MAPR2_MISC_REMAP) {
/* DMA2 Channel 5 mapped at position 60 */
NVIC_ClearPendingIRQ(DMA2_Channel5_IRQn);
NVIC_EnableIRQ(DMA2_Channel5_IRQn);
}
else {
NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn);
NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
}
#else
NVIC_ClearPendingIRQ(DMA2_Channel4_5_IRQn);
NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
#endif
break;
}
DMA2_Channel |= 1 << channel;
break;
#endif
}
}
/**
\fn void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel)
\brief Uninitialize DMA Channel
\param[in] dma DMA number
\param[in] channel DMA channel number
*/
void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel) {
switch (dma) {
case 1:
if (DMA1_Channel == 0) {
// All DMA1 Channels are uninitialized
return;
}
switch (channel) {
case 1:
NVIC_DisableIRQ(DMA1_Channel1_IRQn);
DMA1_Channel1->CCR = 0;
break;
case 2:
NVIC_DisableIRQ(DMA1_Channel2_IRQn);
DMA1_Channel2->CCR = 0;
break;
case 3:
NVIC_DisableIRQ(DMA1_Channel3_IRQn);
DMA1_Channel3->CCR = 0;
break;
case 4:
NVIC_DisableIRQ(DMA1_Channel4_IRQn);
DMA1_Channel4->CCR = 0;
break;
case 5:
NVIC_DisableIRQ(DMA1_Channel5_IRQn);
DMA1_Channel5->CCR = 0;
break;
case 6:
NVIC_DisableIRQ(DMA1_Channel6_IRQn);
DMA1_Channel6->CCR = 0;
break;
case 7:
NVIC_DisableIRQ(DMA1_Channel7_IRQn);
DMA1_Channel7->CCR = 0;
break;
}
DMA1_Channel &= ~(1 << channel);
if (DMA1_Channel == 0){
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
}
break;
#if defined (STM32F10X_ENABLE_DMA2)
case 2:
if (DMA2_Channel == 0) {
// All DMA2 Channels are uninitialized
return;
}
switch (channel) {
case 1:
NVIC_DisableIRQ(DMA2_Channel1_IRQn);
DMA2_Channel1->CCR = 0;
break;
case 2:
NVIC_DisableIRQ(DMA2_Channel2_IRQn);
DMA2_Channel2->CCR = 0;
break;
case 3:
NVIC_DisableIRQ(DMA2_Channel3_IRQn);
DMA2_Channel3->CCR = 0;
break;
case 4:
#if defined (STM32F10X_CL)
NVIC_DisableIRQ(DMA2_Channel4_IRQn);
#else
/* If Channel 5 disabled, disable also Channel 4 */
if (!(DMA2_Channel & (1 << 5))) {
NVIC_DisableIRQ(DMA2_Channel4_5_IRQn);
}
#endif
DMA2_Channel4->CCR = 0;
break;
case 5:
#if defined (STM32F10X_CL)
NVIC_DisableIRQ(DMA2_Channel5_IRQn);
#elif defined (STM32F10X_HD_VL)
if (AFIO->MAPR2 & AFIO_MAPR2_MISC_REMAP) {
/* DMA2 Channel 5 mapped at position 60 */
NVIC_DisableIRQ(DMA2_Channel5_IRQn);
}
else {
/* If Channel 4 disabled, disable also Channel 5 */
if (!(DMA2_Channel & (1 << 4))) {
NVIC_DisableIRQ(DMA2_Channel4_5_IRQn);
}
}
#else
/* If Channel 4 disabled, disable also Channel 5 */
if (!(DMA2_Channel & (1 << 4))) {
NVIC_DisableIRQ(DMA2_Channel4_5_IRQn);
}
#endif
DMA2_Channel5->CCR = 0;
break;
}
DMA2_Channel &= ~(1 << channel);
if (DMA2_Channel == 0){
RCC->AHBENR &= ~RCC_AHBENR_DMA2EN;
}
break;
#endif
}
}
/// DMA1 Channel Events
__weak void DMA1_Channel1_Event (uint32_t event) {;}
__weak void DMA1_Channel2_Event (uint32_t event) {;}
__weak void DMA1_Channel3_Event (uint32_t event) {;}
__weak void DMA1_Channel4_Event (uint32_t event) {;}
__weak void DMA1_Channel5_Event (uint32_t event) {;}
__weak void DMA1_Channel6_Event (uint32_t event) {;}
__weak void DMA1_Channel7_Event (uint32_t event) {;}
#if defined (STM32F10X_ENABLE_DMA2)
/// DMA2 Channel Events
__weak void DMA2_Channel1_Event (uint32_t event) {;}
__weak void DMA2_Channel2_Event (uint32_t event) {;}
__weak void DMA2_Channel3_Event (uint32_t event) {;}
__weak void DMA2_Channel4_Event (uint32_t event) {;}
__weak void DMA2_Channel5_Event (uint32_t event) {;}
#endif
/**
\fn void DMA1_Channel1_IRQHandler (void)
\brief DMA1 Channel0 interrupt handler
*/
void DMA1_Channel1_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 0) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 0;
DMA1_Channel1_Event(events);
}
/**
\fn void DMA1_Channel2_IRQHandler (void)
\brief DMA1 Channel2 interrupt handler
*/
void DMA1_Channel2_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 4) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 4;
DMA1_Channel2_Event(events);
}
/**
\fn void DMA1_Channel3_IRQHandler (void)
\brief DMA1 Channel3 interrupt handler
*/
void DMA1_Channel3_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 8) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 8;
DMA1_Channel3_Event(events);
}
/**
\fn void DMA1_Channel4_IRQHandler (void)
\brief DMA1 Channel4 interrupt handler
*/
void DMA1_Channel4_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 12) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 12;
DMA1_Channel4_Event(events);
}
/**
\fn void DMA1_Channel5_IRQHandler (void)
\brief DMA1 Channel5 interrupt handler
*/
void DMA1_Channel5_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 16) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 16;
DMA1_Channel5_Event(events);
}
/**
\fn void DMA1_Channel6_IRQHandler (void)
\brief DMA1 Channel6 interrupt handler
*/
void DMA1_Channel6_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 20) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 20;
DMA1_Channel6_Event(events);
}
/**
\fn void DMA1_Channel7_IRQHandler (void)
\brief DMA1 Channel7 interrupt handler
*/
void DMA1_Channel7_IRQHandler (void) {
uint32_t events;
events = (DMA1->ISR >> 24) & DMA_CHANNEL_FLAGS;
DMA1->IFCR = events << 24;
DMA1_Channel7_Event(events);
}
#if defined (STM32F10X_ENABLE_DMA2)
/**
\fn void DMA2_Channel1_IRQHandler (void)
\brief DMA2 Channel1 interrupt handler
*/
void DMA2_Channel1_IRQHandler (void) {
uint32_t events;
events = (DMA2->ISR >> 0) & DMA_CHANNEL_FLAGS;
DMA2->IFCR = events << 0;
DMA2_Channel1_Event(events);
}
/**
\fn void DMA2_Channel2_IRQHandler (void)
\brief DMA2 Channel2 interrupt handler
*/
void DMA2_Channel2_IRQHandler (void) {
uint32_t events;
events = (DMA2->ISR >> 4) & DMA_CHANNEL_FLAGS;
DMA2->IFCR = events << 4;
DMA2_Channel2_Event(events);
}
/**
\fn void DMA2_Channel3_IRQHandler (void)
\brief DMA2 Channel3 interrupt handler
*/
void DMA2_Channel3_IRQHandler (void) {
uint32_t events;
events = (DMA2->ISR >> 8) & DMA_CHANNEL_FLAGS;
DMA2->IFCR = events << 8;
DMA2_Channel3_Event(events);
}
#if !defined(STM32F10X_CL)
/**
\fn void DMA2_Channel4_IRQHandler (void)
\brief DMA2 Channel4 interrupt handler
*/
void DMA2_Channel4_IRQHandler (void) {
uint32_t events;
events = (DMA2->ISR >> 12) & DMA_CHANNEL_FLAGS;
DMA2->IFCR = events << 12;
DMA2_Channel4_Event(events);
}
#endif
#if defined(STM32F10X_HD_VL) || defined (STM32F10X_CL)
/**
\fn void DMA2_Channel5_IRQHandler (void)
\brief DMA2 Channel5 interrupt handler
*/
void DMA2_Channel5_IRQHandler (void) {
uint32_t events;
events = (DMA2->ISR >> 16) & DMA_CHANNEL_FLAGS;
DMA2->IFCR = events << 16;
DMA2_Channel5_Event(events);
}
#endif
/**
\fn void DMA2_Channel4_5_IRQHandler (void)
\brief DMA2 Channel 4 and 5 interrupt handler
*/
void DMA2_Channel4_5_IRQHandler (void) {
uint32_t events;
events = (DMA2->ISR >> 12) & DMA_CHANNEL_FLAGS;
if (events) {
/* Channel 4 events */
DMA2->IFCR = events << 12;
DMA2_Channel4_Event(events);
}
events = (DMA2->ISR >> 16) & DMA_CHANNEL_FLAGS;
if (events) {
/* Channel 5 events */
DMA2->IFCR = events << 16;
DMA2_Channel5_Event(events);
}
}
#endif

View File

@ -0,0 +1,156 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2013 ARM Limited. All rights reserved.
*
* $Date: 27. August 2013
* $Revision: V1.01
*
* Project: DMA Driver definitions for ST STM32F10x
* -------------------------------------------------------------------- */
#ifndef __DMA_STM32F10X_H
#define __DMA_STM32F10X_H
#include <stdint.h>
#include <stdbool.h>
#include "stm32f10x.h"
#if defined (__CC_ARM)
#define __FORCE_INLINE static __forceinline
#else
#define __FORCE_INLINE __STATIC_INLINE
#endif
#define _DMAx_CHANNELy(x, y) DMA##x##_Channel##y
#define DMAx_CHANNELy(x, y) _DMAx_CHANNELy(x, y)
#define _DMAx_CHANNELy_EVENT(x, y) DMA##x##_Channel##y##_Event
#define DMAx_CHANNELy_EVENT(x, y) _DMAx_CHANNELy_EVENT(x, y)
// DMA channel Interrupt Flags
#define DMA_CHANNEL_GLOBAL_INTERRUPT (1UL<<0)
#define DMA_CHANNEL_TRANSFER_COMPLETE (1UL<<1)
#define DMA_CHANNEL_HALF_TRANSFER (1UL<<2)
#define DMA_CHANNEL_TRANSFER_ERROR (1UL<<3)
#define DMA_CHANNEL_FLAGS (DMA_CHANNEL_TRANSFER_ERROR | \
DMA_CHANNEL_HALF_TRANSFER | \
DMA_CHANNEL_TRANSFER_COMPLETE | \
DMA_CHANNEL_GLOBAL_INTERRUPT)
// DMA channel Configuration Register definitions
#define DMA_TRANSFER_ERROR_INTERRUPT DMA_CCR1_TEIE
#define DMA_HALF_TRANSFER_INTERRUPT DMA_CCR1_HTIE
#define DMA_TRANSFER_COMPLETE_INTERRUPT DMA_CCR1_TCIE
#define DMA_PERIPHERAL_TO_MEMORY 0
#define DMA_READ_MEMORY DMA_CCR1_DIR
#define DMA_MEMORY_TO_MEMORY DMA_CCR1_MEM2MEM
#define DMA_CIRCULAR_MODE DMA_CCR1_CIRC
#define DMA_PERIPHERAL_INCREMENT DMA_CCR1_PINC
#define DMA_MEMORY_INCREMENT DMA_CCR1_MINC
#define DMA_PERIPHERAL_DATA_8BIT 0
#define DMA_PERIPHERAL_DATA_16BIT DMA_CCR1_PSIZE_0
#define DMA_PERIPHERAL_DATA_32BIT DMA_CCR1_PSIZE_1
#define DMA_MEMORY_DATA_8BIT 0
#define DMA_MEMORY_DATA_16BIT DMA_CCR1_MSIZE_0
#define DMA_MEMORY_DATA_32BIT DMA_CCR1_MSIZE_1
#define DMA_PRIORITY_POS 12
#define DMA_PRIORITY_MASK DMA_CCR1_PL
#define DMA_CHANNEL_EN DMA_CCR1_EN
// DMA Information definitions
typedef struct _DMA_INFO {
DMA_Channel_TypeDef *ptr_channel;
uint8_t dma;
uint8_t channel;
uint8_t priority;
} DMA_INFO;
/// DMA Functions
/**
\fn void DMA_ChannelInitialize (uint32_t dma, uint32_t channel)
\brief Initialize DMA Channel
\param[in] dma DMA number
\param[in] channel DMA channel number
*/
extern void DMA_ChannelInitialize (uint32_t dma, uint32_t channel);
/**
\fn void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel)
\brief Uninitialize DMA channel
\param[in] dma DMA number
\param[in] channel DMA channel number
*/
extern void DMA_ChannelUninitialize (uint32_t dma, uint32_t channel);
/**
\fn void DMA_ChannelConfigure (DMA_Channel_TypeDef *DMA_Channel,
uint32_t ccr,
uint32_t cpar,
uint32_t cmar,
uint32_t cndtr);
\brief Configure DMA channel for next transfer
\param[in] DMA_Channel specifies pointer to DMA channel peripheral
\param[in] ccr Configuration register value
\param[in] cpar Peripheral address register value
\param[in] cmar Memory address register value
\param[in] cndtr Number of data transfer register value
*/
__FORCE_INLINE void DMA_ChannelConfigure (DMA_Channel_TypeDef *DMA_Channel,
uint32_t ccr,
uint32_t cpar,
uint32_t cmar,
uint32_t cndtr) {
DMA_Channel->CCR = ccr;
DMA_Channel->CPAR = cpar;
DMA_Channel->CMAR = cmar;
DMA_Channel->CNDTR = cndtr;
}
/**
\fn void DMA_ChannelEnable (DMA_Channel_TypeDef *DMA_Channel)
\brief Enable channel and/or start memory to memory transfer
\param[in] DMA_Channel Pointer to DMA channel peripheral
*/
__FORCE_INLINE void DMA_ChannelEnable (DMA_Channel_TypeDef *DMA_Channel) {
DMA_Channel->CCR |= DMA_CHANNEL_EN;
}
/**
\fn void DMA_ChannelDisable (DMA_Channel_TypeDef *DMA_Channel)
\brief Disable channel and/or stop memory to memory transfer
\param[in] DMA_Channel Pointer to DMA channel peripheral
*/
__FORCE_INLINE void DMA_ChannelDisable (DMA_Channel_TypeDef *DMA_Channel) {
DMA_Channel->CCR &= ~DMA_CHANNEL_EN;
}
/**
\fn bool DMA_ChannelStatus (DMA_Channel_TypeDef *DMA_Channel)
\brief Check if channel is enabled or disabled
\param[in] DMA_Channel Pointer to DMA channel peripheral
\return Channel Status
- \b true Enabled
- \b false Disabled
*/
__FORCE_INLINE bool DMA_ChannelStatus (DMA_Channel_TypeDef *DMA_Channel) {
return (DMA_Channel->CCR & DMA_CHANNEL_EN) ? true : false;
}
/**
\fn uint32_t DMA_ChannelTransferItemCount (DMA_Channel_TypeDef *DMA_Channel)
\brief Get number of data items to transfer
\param[in] DMA_channel Pointer to DMA channel peripheral
\return Number of data items to transfer
*/
__FORCE_INLINE uint32_t DMA_ChannelTransferItemCount (DMA_Channel_TypeDef *DMA_Channel) {
return DMA_Channel->CNDTR;
}
#endif /* __DMA_STM32F10X_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,231 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2018 Arm Limited
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 4. October 2018
* $Revision: V2.1
*
* Project: Ethernet Media Access (MAC) Definitions for STM32F10x
* -------------------------------------------------------------------------- */
#ifndef __EMAC_STM32F10X_H
#define __EMAC_STM32F10X_H
#include <string.h>
#include "Driver_ETH_MAC.h"
#include "stm32f10x.h"
#include "RTE_Components.h"
#include "RTE_Device.h"
#if (defined(RTE_Drivers_ETH_MAC0) && !RTE_ETH)
#error "Ethernet not configured in RTE_Device.h!"
#endif
#if (RTE_ETH_MII && RTE_ETH_RMII)
#error "Ethernet interface configuration in RTE_Device.h is invalid!"
#endif
/* MDC management clock prescaler */
#if (RTE_HCLK >= 60000000)
#define MACMIIAR_CR_Val ETH_MACMIIAR_CR_Div42
#elif (RTE_HCLK >= 35000000)
#define MACMIIAR_CR_Val ETH_MACMIIAR_CR_Div26
#elif (RTE_HCLK >= 20000000)
#define MACMIIAR_CR_Val ETH_MACMIIAR_CR_Div16
#error "HCLK too slow for Ethernet! Check settings in RTE_Device.h!"
#endif
#define ETH_MDC_GPIOx RTE_ETH_MDI_MDC_PORT
#define ETH_MDC_GPIO_Pin RTE_ETH_MDI_MDC_PIN
#define ETH_MDIO_GPIOx RTE_ETH_MDI_MDIO_PORT
#define ETH_MDIO_GPIO_Pin RTE_ETH_MDI_MDIO_PIN
#if (RTE_ETH_MII)
#define ETH_MII 1
#define ETH_TXD0_GPIOx RTE_ETH_MII_TXD0_PORT
#define ETH_TXD0_GPIO_Pin RTE_ETH_MII_TXD0_PIN
#define ETH_TXD1_GPIOx RTE_ETH_MII_TXD1_PORT
#define ETH_TXD1_GPIO_Pin RTE_ETH_MII_TXD1_PIN
#define ETH_TXD2_GPIOx RTE_ETH_MII_TXD2_PORT
#define ETH_TXD2_GPIO_Pin RTE_ETH_MII_TXD2_PIN
#define ETH_TXD3_GPIOx RTE_ETH_MII_TXD3_PORT
#define ETH_TXD3_GPIO_Pin RTE_ETH_MII_TXD3_PIN
#define ETH_RXD0_GPIOx RTE_ETH_MII_RXD0_PORT
#define ETH_RXD0_GPIO_Pin RTE_ETH_MII_RXD0_PIN
#define ETH_RXD1_GPIOx RTE_ETH_MII_RXD1_PORT
#define ETH_RXD1_GPIO_Pin RTE_ETH_MII_RXD1_PIN
#define ETH_RXD2_GPIOx RTE_ETH_MII_RXD2_PORT
#define ETH_RXD2_GPIO_Pin RTE_ETH_MII_RXD2_PIN
#define ETH_RXD3_GPIOx RTE_ETH_MII_RXD3_PORT
#define ETH_RXD3_GPIO_Pin RTE_ETH_MII_RXD3_PIN
#define ETH_TX_EN_GPIOx RTE_ETH_MII_TX_EN_PORT
#define ETH_TX_EN_GPIO_Pin RTE_ETH_MII_TX_EN_PIN
#define ETH_TX_CLK_GPIOx RTE_ETH_MII_TX_CLK_PORT
#define ETH_TX_CLK_GPIO_Pin RTE_ETH_MII_TX_CLK_PIN
#define ETH_RX_CLK_GPIOx RTE_ETH_MII_RX_CLK_PORT
#define ETH_RX_CLK_GPIO_Pin RTE_ETH_MII_RX_CLK_PIN
#define ETH_CRS_GPIOx RTE_ETH_MII_CRS_PORT
#define ETH_CRS_GPIO_Pin RTE_ETH_MII_CRS_PIN
#define ETH_COL_GPIOx RTE_ETH_MII_COL_PORT
#define ETH_COL_GPIO_Pin RTE_ETH_MII_COL_PIN
#define ETH_RX_DV_GPIOx RTE_ETH_MII_RX_DV_PORT
#define ETH_RX_DV_GPIO_Pin RTE_ETH_MII_RX_DV_PIN
#define ETH_RX_ER_GPIOx RTE_ETH_MII_RX_ER_PORT
#define ETH_RX_ER_GPIO_Pin RTE_ETH_MII_RX_ER_PIN
#else
#define ETH_MII 0
#define ETH_TXD0_GPIOx RTE_ETH_RMII_TXD0_PORT
#define ETH_TXD0_GPIO_Pin RTE_ETH_RMII_TXD0_PIN
#define ETH_TXD1_GPIOx RTE_ETH_RMII_TXD1_PORT
#define ETH_TXD1_GPIO_Pin RTE_ETH_RMII_TXD1_PIN
#define ETH_RXD0_GPIOx RTE_ETH_RMII_RXD0_PORT
#define ETH_RXD0_GPIO_Pin RTE_ETH_RMII_RXD0_PIN
#define ETH_RXD1_GPIOx RTE_ETH_RMII_RXD1_PORT
#define ETH_RXD1_GPIO_Pin RTE_ETH_RMII_RXD1_PIN
#define ETH_TX_EN_GPIOx RTE_ETH_RMII_TX_EN_PORT
#define ETH_TX_EN_GPIO_Pin RTE_ETH_RMII_TX_EN_PIN
#define ETH_REF_CLK_GPIOx RTE_ETH_RMII_REF_CLK_PORT
#define ETH_REF_CLK_GPIO_Pin RTE_ETH_RMII_REF_CLK_PIN
#define ETH_CRS_DV_GPIOx RTE_ETH_RMII_CRS_DV_PORT
#define ETH_CRS_DV_GPIO_Pin RTE_ETH_RMII_CRS_DV_PIN
#endif /* RTE_ETH_RMII */
/* EMAC Driver state flags */
#define EMAC_FLAG_INIT (1 << 0) // Driver initialized
#define EMAC_FLAG_POWER (1 << 1) // Driver power on
#define EMAC_FLAG_DMA_INIT (1 << 2) // DMA Initialized
/* PTP subsecond increment value */
#define PTPSSIR_Val(hclk) ((0x7FFFFFFFU + (hclk)/2U) / (hclk))
/* TDES0 - DMA Descriptor TX Packet Control/Status */
#define DMA_TX_OWN 0x80000000U // Own bit 1=DMA,0=CPU
#define DMA_TX_IC 0x40000000U // Interrupt on completition
#define DMA_TX_LS 0x20000000U // Last segment
#define DMA_TX_FS 0x10000000U // First segment
#define DMA_TX_DC 0x08000000U // Disable CRC
#define DMA_TX_DP 0x04000000U // Disable pad
#define DMA_TX_TTSE 0x02000000U // Transmit time stamp enable
#define DMA_TX_CIC 0x00C00000U // Checksum insertion control
#define DMA_TX_TER 0x00200000U // Transmit end of ring
#define DMA_TX_TCH 0x00100000U // Second address chained
#define DMA_TX_TTSS 0x00020000U // Transmit time stamp status
#define DMA_TX_IHE 0x00010000U // IP header error status
#define DMA_TX_ES 0x00008000U // Error summary
#define DMA_TX_JT 0x00004000U // Jabber timeout
#define DMA_TX_FF 0x00002000U // Frame flushed
#define DMA_TX_IPE 0x00001000U // IP payload error
#define DMA_TX_LC 0x00000800U // Loss of carrier
#define DMA_TX_NC 0x00000400U // No carrier
#define DMA_TX_LCOL 0x00000200U // Late collision
#define DMA_TX_EC 0x00000100U // Excessive collision
#define DMA_TX_VF 0x00000080U // VLAN frame
#define DMA_TX_CC 0x00000078U // Collision count
#define DMA_TX_ED 0x00000004U // Excessive deferral
#define DMA_TX_UF 0x00000002U // Underflow error
#define DMA_TX_DB 0x00000001U // Deferred bit
/* TDES1 - DMA Descriptor TX Packet Control */
#define DMA_RX_TBS2 0x1FFF0000U // Transmit buffer 2 size
#define DMA_RX_TBS1 0x00001FFFU // Transmit buffer 1 size
/* RDES0 - DMA Descriptor RX Packet Status */
#define DMA_RX_OWN 0x80000000U // Own bit 1=DMA,0=CPU
#define DMA_RX_AFM 0x40000000U // Destination address filter fail
#define DMA_RX_FL 0x3FFF0000U // Frame length mask
#define DMA_RX_ES 0x00008000U // Error summary
#define DMA_RX_DE 0x00004000U // Descriptor error
#define DMA_RX_SAF 0x00002000U // Source address filter fail
#define DMA_RX_LE 0x00001000U // Length error
#define DMA_RX_OE 0x00000800U // Overflow error
#define DMA_RX_VLAN 0x00000400U // VLAN tag
#define DMA_RX_FS 0x00000200U // First descriptor
#define DMA_RX_LS 0x00000100U // Last descriptor
#define DMA_RX_IPHCE 0x00000080U // IPv4 header checksum error
#define DMA_RX_LC 0x00000040U // late collision
#define DMA_RX_FT 0x00000020U // Frame type
#define DMA_RX_RWT 0x00000010U // Receive watchdog timeout
#define DMA_RX_RE 0x00000008U // Receive error
#define DMA_RX_DRE 0x00000004U // Dribble bit error
#define DMA_RX_CE 0x00000002U // CRC error
#define DMA_RX_RMAM 0x00000001U // Rx MAC adr.match/payload cks.error
/* RDES1 - DMA Descriptor RX Packet Control */
#define DMA_RX_DIC 0x80000000U // Disable interrupt on completion
#define DMA_RX_RBS2 0x1FFF0000U // Receive buffer 2 size
#define DMA_RX_RER 0x00008000U // Receive end of ring
#define DMA_RX_RCH 0x00004000U // Second address chained
#define DMA_RX_RBS1 0x00001FFFU // Receive buffer 1 size
/* EMAC DMA RX Descriptor */
typedef struct rx_desc {
uint32_t volatile Stat;
uint32_t Ctrl;
uint8_t const *Addr;
struct rx_desc *Next;
#if ((EMAC_CHECKSUM_OFFLOAD != 0) || (EMAC_TIME_STAMP != 0))
uint32_t ExtStat;
uint32_t Reserved[1];
uint32_t TimeLo;
uint32_t TimeHi;
#endif
} RX_Desc;
/* EMAC DMA TX Descriptor */
typedef struct tx_desc {
uint32_t volatile CtrlStat;
uint32_t Size;
uint8_t *Addr;
struct tx_desc *Next;
#if ((EMAC_CHECKSUM_OFFLOAD != 0) || (EMAC_TIME_STAMP != 0))
uint32_t Reserved[2];
uint32_t TimeLo;
uint32_t TimeHi;
#endif
} TX_Desc;
/* EMAC Pin Descriptor */
typedef struct _ETH_PIN {
GPIO_TypeDef *port;
uint16_t pin;
} ETH_PIN;
/* EMAC Driver Control Information */
typedef struct {
ARM_ETH_MAC_SignalEvent_t cb_event; // Event callback
uint8_t flags; // Control and state flags
uint8_t tx_index; // Transmit descriptor index
uint8_t rx_index; // Receive descriptor index
#if (EMAC_CHECKSUM_OFFLOAD)
bool tx_cks_offload; // Checksum offload enabled/disabled
#endif
#if (EMAC_TIME_STAMP)
uint8_t tx_ts_index; // Transmit Timestamp descriptor index
#endif
uint8_t *frame_end; // End of assembled frame fragments
} EMAC_CTRL;
#endif /* __EMAC_STM32F10X_H */

View File

@ -0,0 +1,169 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2016 ARM Limited. All rights reserved.
*
* $Date: 26. April 2016
* $Revision: V1.3
*
* Project: GPIO Driver for ST STM32F10x
* -------------------------------------------------------------------- */
#include "GPIO_STM32F10x.h"
/* History:
* Version 1.3
* Corrected corruption of Serial wire JTAG pins alternate function configuration.
* Version 1.2
* Added GPIO_GetPortClockState function
* GPIO_PinConfigure function enables GPIO peripheral clock, if not already enabled
* Version 1.1
* GPIO_PortClock and GPIO_PinConfigure functions rewritten
* GPIO_STM32F1xx header file cleaned up and simplified
* GPIO_AFConfigure function and accompanying definitions added
* Version 1.0
* Initial release
*/
/* Serial wire JTAG pins alternate function Configuration
* Can be user defined by C preprocessor:
* AFIO_SWJ_FULL, AFIO_SWJ_FULL_NO_NJTRST, AFIO_SWJ_JTAG_NO_SW, AFIO_SWJ_NO_JTAG_NO_SW
*/
#ifndef AFIO_MAPR_SWJ_CFG_VAL
#define AFIO_MAPR_SWJ_CFG_VAL (AFIO_SWJ_FULL) // Full SWJ (JTAG-DP + SW-DP)
#endif
/**
\fn void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool en)
\brief Port Clock Control
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] enable Enable or disable clock
*/
void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool enable) {
if (enable) {
if (GPIOx == GPIOA) RCC->APB2ENR |= (1U << 2);
else if (GPIOx == GPIOB) RCC->APB2ENR |= (1U << 3);
else if (GPIOx == GPIOC) RCC->APB2ENR |= (1U << 4);
else if (GPIOx == GPIOD) RCC->APB2ENR |= (1U << 5);
else if (GPIOx == GPIOE) RCC->APB2ENR |= (1U << 6);
else if (GPIOx == GPIOF) RCC->APB2ENR |= (1U << 7);
else if (GPIOx == GPIOG) RCC->APB2ENR |= (1U << 8);
} else {
if (GPIOx == GPIOA) RCC->APB2ENR &= ~(1U << 2);
else if (GPIOx == GPIOB) RCC->APB2ENR &= ~(1U << 3);
else if (GPIOx == GPIOC) RCC->APB2ENR &= ~(1U << 4);
else if (GPIOx == GPIOD) RCC->APB2ENR &= ~(1U << 5);
else if (GPIOx == GPIOE) RCC->APB2ENR &= ~(1U << 6);
else if (GPIOx == GPIOF) RCC->APB2ENR &= ~(1U << 7);
else if (GPIOx == GPIOG) RCC->APB2ENR &= ~(1U << 8);
}
}
/**
\fn bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx)
\brief Get GPIO port clock state
\param[in] GPIOx Pointer to GPIO peripheral
\return true - enabled
false - disabled
*/
bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx) {
if (GPIOx == GPIOA) { return ((RCC->APB2ENR & (1U << 2)) != 0U); }
else if (GPIOx == GPIOB) { return ((RCC->APB2ENR & (1U << 3)) != 0U); }
else if (GPIOx == GPIOC) { return ((RCC->APB2ENR & (1U << 4)) != 0U); }
else if (GPIOx == GPIOD) { return ((RCC->APB2ENR & (1U << 5)) != 0U); }
else if (GPIOx == GPIOE) { return ((RCC->APB2ENR & (1U << 6)) != 0U); }
else if (GPIOx == GPIOF) { return ((RCC->APB2ENR & (1U << 7)) != 0U); }
else if (GPIOx == GPIOG) { return ((RCC->APB2ENR & (1U << 8)) != 0U); }
return false;
}
/**
\fn bool GPIO_PinConfigure (GPIO_TypeDef *GPIOx,
uint32_t num,
GPIO_CONF conf,
GPIO_MODE mode)
\brief Configure port pin
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] num Port pin number
\param[in] mode \ref GPIO_MODE
\param[in] conf \ref GPIO_CONF
\return true - success
false - error
*/
bool GPIO_PinConfigure(GPIO_TypeDef *GPIOx, uint32_t num, GPIO_CONF conf,
GPIO_MODE mode) {
__IO uint32_t *reg;
if (num > 15) return false;
if (GPIO_GetPortClockState(GPIOx) == false) {
/* Enable GPIOx peripheral clock */
GPIO_PortClock (GPIOx, true);
}
if (mode == GPIO_MODE_INPUT) {
if (conf == GPIO_IN_PULL_DOWN) {
/* Enable pull down on selected input */
GPIOx->ODR &= ~(1 << num);
}
else if (conf == GPIO_IN_PULL_UP) {
/* Enable pull up on selected input */
conf &= ~1;
GPIOx->ODR |= (1 << num);
}
}
if (num < 8) {
reg = &GPIOx->CRL;
}
else {
num -= 8;
reg = &GPIOx->CRH;
}
*reg &= ~(0xF << (num << 2));
*reg |= ((conf << 2) | mode) << (num << 2);
return true;
}
/**
\fn void GPIO_AFConfigure (AFIO_REMAP af_type)
\brief Configure alternate functions
\param[in] af_type Alternate function remap type
*/
void GPIO_AFConfigure (AFIO_REMAP af_type) {
uint32_t msk, val;
volatile uint32_t mapr;
if (af_type != AFIO_UNAVAILABLE_REMAP) {
msk = (af_type >> 5) & 0x07;
val = (af_type >> 8) & 0x0F;
if (!(RCC->APB2ENR & RCC_APB2ENR_AFIOEN)) {
/* Enable AFIO peripheral clock */
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
}
if (af_type & (1 << 12)) {
/* AF remap and debug I/O config register 2 */
mapr = AFIO->MAPR2;
mapr &= ~(msk << (af_type & 0x1F));
mapr |= (val << (af_type & 0x1F));
AFIO->MAPR2 = mapr;
}
else {
/* AF remap and debug I/O config register */
mapr = AFIO->MAPR;
mapr &= ~(msk << (af_type & 0x1F));
mapr |= (val << (af_type & 0x1F));
/* Serial wire JTAG configuration */
msk = (AFIO_MAPR_SWJ_CFG_VAL >> 5) & 0x07;
val = (AFIO_MAPR_SWJ_CFG_VAL >> 8) & 0x0F;
mapr &= ~(msk << (AFIO_MAPR_SWJ_CFG_VAL & 0x1F));
mapr |= (val << (AFIO_MAPR_SWJ_CFG_VAL & 0x1F));
AFIO->MAPR = mapr;
}
}
}

View File

@ -0,0 +1,241 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2013 ARM Limited. All rights reserved.
*
* $Date: 26. August 2013
* $Revision: V1.2
*
* Project: GPIO Driver definitions for ST STM32F10x
* -------------------------------------------------------------------- */
#ifndef __GPIO_STM32F10X_H
#define __GPIO_STM32F10X_H
#include <stdbool.h>
#include "stm32f10x.h"
#if defined (__CC_ARM)
#define __FORCE_INLINE static __forceinline
#else
#define __FORCE_INLINE __STATIC_INLINE
#endif
/// GPIO Pin identifier
typedef struct _GPIO_PIN_ID {
GPIO_TypeDef *port;
uint8_t num;
} GPIO_PIN_ID;
/// Port Mode
typedef enum {
GPIO_MODE_INPUT = 0x00, /// GPIO is input
GPIO_MODE_OUT10MHZ = 0x01, /// Max output Speed 10MHz
GPIO_MODE_OUT2MHZ = 0x02, /// Max output Speed 2MHz
GPIO_MODE_OUT50MHZ = 0x03 /// Max output Speed 50MHz
} GPIO_MODE;
/// Port Conf
typedef enum {
GPIO_OUT_PUSH_PULL = 0x00, /// general purpose output push-pull
GPIO_OUT_OPENDRAIN = 0x01, /// general purpose output open-drain
GPIO_AF_PUSHPULL = 0x02, /// alternate function push-pull
GPIO_AF_OPENDRAIN = 0x03, /// alternate function open-drain
GPIO_IN_ANALOG = 0x00, /// input analog
GPIO_IN_FLOATING = 0x01, /// input floating
GPIO_IN_PULL_DOWN = 0x02, /// alternate function push-pull
GPIO_IN_PULL_UP = 0x03 /// alternate function pull up
} GPIO_CONF;
/* Alternate function definition macro */
#define AFIO_FUNC_DEF(bit, mask, val, reg) ((bit) | (mask << 5) | (val << 8) | (reg << 12))
/// Alternate function I/O remap
typedef enum {
/* AF remap and debug I/O config register */
AFIO_SPI1_NO_REMAP = AFIO_FUNC_DEF (0, 1, 0, 0),
AFIO_SPI1_REMAP = AFIO_FUNC_DEF (0, 1, 1, 0),
AFIO_I2C1_NO_REMAP = AFIO_FUNC_DEF (1, 1, 0, 0),
AFIO_I2C1_REMAP = AFIO_FUNC_DEF (1, 1, 1, 0),
AFIO_USART1_NO_REMAP = AFIO_FUNC_DEF (2, 1, 0, 0),
AFIO_USART1_REMAP = AFIO_FUNC_DEF (2, 1, 1, 0),
AFIO_USART2_NO_REMAP = AFIO_FUNC_DEF (3, 1, 0, 0),
AFIO_USART2_REMAP = AFIO_FUNC_DEF (3, 1, 1, 0),
AFIO_USART3_NO_REMAP = AFIO_FUNC_DEF (4, 3, 0, 0),
AFIO_USART3_REMAP_PARTIAL = AFIO_FUNC_DEF (4, 3, 1, 0),
AFIO_USART3_REMAP_FULL = AFIO_FUNC_DEF (4, 3, 3, 0),
AFIO_TIM1_NO_REMAP = AFIO_FUNC_DEF (6, 3, 0, 0),
AFIO_TIM1_REMAP_PARTIAL = AFIO_FUNC_DEF (6, 3, 1, 0),
AFIO_TIM1_REMAP_FULL = AFIO_FUNC_DEF (6, 3, 3, 0),
AFIO_TIM2_NO_REMAP = AFIO_FUNC_DEF (8, 3, 0, 0),
AFIO_TIM2_REMAP_PARTIAL_1 = AFIO_FUNC_DEF (8, 3, 1, 0),
AFIO_TIM2_REMAP_PARTIAL_2 = AFIO_FUNC_DEF (8, 3, 2, 0),
AFIO_TIM2_REMAP_FULL = AFIO_FUNC_DEF (8, 3, 3, 0),
AFIO_TIM3_NO_REMAP = AFIO_FUNC_DEF (10, 3, 0, 0),
AFIO_TIM3_REMAP_PARTIAL = AFIO_FUNC_DEF (10, 3, 2, 0),
AFIO_TIM3_REMAP_FULL = AFIO_FUNC_DEF (10, 3, 3, 0),
AFIO_TIM4_NO_REMAP = AFIO_FUNC_DEF (12, 1, 0, 0),
AFIO_TIM4_REMAP = AFIO_FUNC_DEF (12, 1, 1, 0),
AFIO_CAN_PA11_PA12 = AFIO_FUNC_DEF (13, 3, 0, 0),
AFIO_CAN_PB8_PB9 = AFIO_FUNC_DEF (13, 3, 2, 0),
AFIO_CAN_PD0_PD1 = AFIO_FUNC_DEF (13, 3, 3, 0),
AFIO_PD01_NO_REMAP = AFIO_FUNC_DEF (15, 1, 0, 0),
AFIO_PD01_REMAP = AFIO_FUNC_DEF (15, 1, 1, 0),
AFIO_TIM5CH4_NO_REMAP = AFIO_FUNC_DEF (16, 1, 0, 0),
AFIO_TIM5CH4_REMAP = AFIO_FUNC_DEF (16, 1, 1, 0),
AFIO_ADC1_ETRGINJ_NO_REMAP = AFIO_FUNC_DEF (17, 1, 0, 0),
AFIO_ADC1_ETRGINJ_REMAP = AFIO_FUNC_DEF (17, 1, 1, 0),
AFIO_ADC1_ETRGREG_NO_REMAP = AFIO_FUNC_DEF (18, 1, 0, 0),
AFIO_ADC1_ETRGREG_REMAP = AFIO_FUNC_DEF (18, 1, 1, 0),
AFIO_ADC2_ETRGINJ_NO_REMAP = AFIO_FUNC_DEF (19, 1, 0, 0),
AFIO_ADC2_ETRGINJ_REMAP = AFIO_FUNC_DEF (19, 1, 1, 0),
AFIO_ADC2_ETRGREG_NO_REMAP = AFIO_FUNC_DEF (20, 1, 0, 0),
AFIO_ADC2_ETRGREG_REMAP = AFIO_FUNC_DEF (20, 1, 1, 0),
#if defined(STM32F10X_CL)
AFIO_ETH_NO_REMAP = AFIO_FUNC_DEF (21, 1, 0, 0),
AFIO_ETH_REMAP = AFIO_FUNC_DEF (21, 1, 1, 0),
AFIO_CAN2_NO_REMAP = AFIO_FUNC_DEF (22, 1, 0, 0),
AFIO_CAN2_REMAP = AFIO_FUNC_DEF (22, 1, 1, 0),
AFIO_ETH_MII_SEL = AFIO_FUNC_DEF (23, 1, 0, 0),
AFIO_ETH_RMII_SEL = AFIO_FUNC_DEF (23, 1, 1, 0),
#endif
AFIO_SWJ_FULL = AFIO_FUNC_DEF (24, 7, 0, 0),
AFIO_SWJ_FULL_NO_NJTRST = AFIO_FUNC_DEF (24, 7, 1, 0),
AFIO_SWJ_JTAG_NO_SW = AFIO_FUNC_DEF (24, 7, 2, 0),
AFIO_SWJ_NO_JTAG_NO_SW = AFIO_FUNC_DEF (24, 7, 4, 0),
#if defined(STM32F10X_CL)
AFIO_SPI3_NO_REMAP = AFIO_FUNC_DEF (28, 1, 0, 0),
AFIO_SPI3_REMAP = AFIO_FUNC_DEF (28, 1, 1, 0),
AFIO_TIM2ITR_NO_REMAP = AFIO_FUNC_DEF (29, 1, 0, 0),
AFIO_TIM2ITR_REMAP = AFIO_FUNC_DEF (29, 1, 1, 0),
AFIO_PTP_PPS_NO_REMAP = AFIO_FUNC_DEF (30, 1, 0, 0),
AFIO_PTP_PPS_REMAP = AFIO_FUNC_DEF (30, 1, 1, 0),
#endif
/* AF remap and debug I/O config register 2 */
AFIO_TIM15_NO_REMAP = AFIO_FUNC_DEF (0, 1, 0, 1),
AFIO_TIM15_REMAP = AFIO_FUNC_DEF (0, 1, 1, 1),
AFIO_TIM16_NO_REMAP = AFIO_FUNC_DEF (1, 1, 0, 1),
AFIO_TIM16_REMAP = AFIO_FUNC_DEF (1, 1, 1, 1),
AFIO_TIM17_NO_REMAP = AFIO_FUNC_DEF (2, 1, 0, 1),
AFIO_TIM17_REMAP = AFIO_FUNC_DEF (2, 1, 1, 1),
AFIO_CEC_NO_REMAP = AFIO_FUNC_DEF (3, 1, 0, 1),
AFIO_CEC_REMAP = AFIO_FUNC_DEF (3, 1, 1, 1),
AFIO_TIM1_DMA_NO_REMAP = AFIO_FUNC_DEF (4, 1, 0, 1),
AFIO_TIM1_DMA_REMAP = AFIO_FUNC_DEF (4, 1, 1, 1),
AFIO_TIM9_NO_REMAP = AFIO_FUNC_DEF (5, 1, 0, 1),
AFIO_TIM9_REMAP = AFIO_FUNC_DEF (5, 1, 1, 1),
AFIO_TIM10_NO_REMAP = AFIO_FUNC_DEF (6, 1, 0, 1),
AFIO_TIM10_REMAP = AFIO_FUNC_DEF (6, 1, 1, 1),
AFIO_TIM11_NO_REMAP = AFIO_FUNC_DEF (7, 1, 0, 1),
AFIO_TIM11_REMAP = AFIO_FUNC_DEF (7, 1, 1, 1),
AFIO_TIM13_NO_REMAP = AFIO_FUNC_DEF (8, 1, 0, 1),
AFIO_TIM13_REMAP = AFIO_FUNC_DEF (8, 1, 0, 1),
AFIO_TIM14_NO_REMAP = AFIO_FUNC_DEF (9, 1, 0, 1),
AFIO_TIM14_REMAP = AFIO_FUNC_DEF (9, 1, 1, 1),
AFIO_FSMC_NADV_NO_REMAP = AFIO_FUNC_DEF (10, 1, 0, 1),
AFIO_FSMC_NADV_REMAP = AFIO_FUNC_DEF (10, 1, 1, 1),
AFIO_TIM67_DAC_DMA_NO_REMAP = AFIO_FUNC_DEF(11, 1, 0, 1),
AFIO_TIM67_DAC_DMA_REMAP = AFIO_FUNC_DEF (11, 1, 1, 1),
AFIO_TIM12_NO_REMAP = AFIO_FUNC_DEF (12, 1, 0, 1),
AFIO_TIM12_REMAP = AFIO_FUNC_DEF (12, 1, 1, 1),
AFIO_MISC_NO_REMAP = AFIO_FUNC_DEF (13, 1, 0, 1),
AFIO_MISC_REMAP = AFIO_FUNC_DEF (13, 1, 1, 1),
/* Reserved value */
AFIO_UNAVAILABLE_REMAP = AFIO_FUNC_DEF (0, 0, 0, 0)
} AFIO_REMAP;
/**
\fn void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool en)
\brief Port Clock Control
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] enable Enable or disable clock
*/
extern void GPIO_PortClock (GPIO_TypeDef *GPIOx, bool enable);
/**
\fn bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx)
\brief Get GPIO port clock state
\param[in] GPIOx Pointer to GPIO peripheral
\return true - enabled
false - disabled
*/
extern bool GPIO_GetPortClockState (GPIO_TypeDef *GPIOx);
/**
\fn bool GPIO_PinConfigure (GPIO_TypeDef *GPIOx,
uint32_t num,
GPIO_CONF conf,
GPIO_MODE mode)
\brief Configure port pin
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] num Port pin number
\param[in] mode \ref GPIO_MODE
\param[in] conf \ref GPIO_CONF
\return true - success
false - error
*/
bool GPIO_PinConfigure(GPIO_TypeDef *GPIOx,
uint32_t num,
GPIO_CONF conf,
GPIO_MODE mode);
/**
\fn void GPIO_PinWrite (GPIO_TypeDef *GPIOx, uint32_t num, uint32_t val)
\brief Write port pin
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] num Port pin number
\param[in] val Port pin value (0 or 1)
*/
__FORCE_INLINE void GPIO_PinWrite (GPIO_TypeDef *GPIOx, uint32_t num, uint32_t val) {
if (val & 1) {
GPIOx->BSRR = (1UL << num); // set
} else {
GPIOx->BSRR = (1UL << (num + 16)); // clr
}
}
/**
\fn uint32_t GPIO_PinRead (GPIO_TypeDef *GPIOx, uint32_t num)
\brief Read port pin
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] num Port pin number
\return pin value (0 or 1)
*/
__FORCE_INLINE uint32_t GPIO_PinRead (GPIO_TypeDef *GPIOx, uint32_t num) {
return ((GPIOx->IDR >> num) & 1);
}
/**
\fn void GPIO_PortWrite (GPIO_TypeDef *GPIOx, uint16_t mask, uint16_t val)
\brief Write port pins
\param[in] GPIOx Pointer to GPIO peripheral
\param[in] mask Selected pins
\param[in] val Pin values
*/
__FORCE_INLINE void GPIO_PortWrite (GPIO_TypeDef *GPIOx, uint16_t mask, uint16_t val) {
GPIOx->ODR = (GPIOx->ODR & ~mask) | val;
}
/**
\fn uint16_t GPIO_PortRead (GPIO_TypeDef *GPIOx)
\brief Read port pins
\param[in] GPIOx Pointer to GPIO peripheral
\return port pin inputs
*/
__FORCE_INLINE uint16_t GPIO_PortRead (GPIO_TypeDef *GPIOx) {
return (GPIOx->IDR);
}
/**
\fn void GPIO_AFConfigure (AFIO_REMAP af_type)
\brief Configure alternate functions
\param[in] af_type Alternate function remap type
*/
void GPIO_AFConfigure (AFIO_REMAP af_type);
#endif /* __GPIO_STM32F10X_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,198 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2015 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 22. September 2015
* $Revision: V2.0
*
* Project: I2C Driver definitions for STMicroelectronics STM32F10x
* -------------------------------------------------------------------------- */
#ifndef __I2C_STM32F10X_H
#define __I2C_STM32F10X_H
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "DMA_STM32F10x.h"
#include "Driver_I2C.h"
#include "RTE_Components.h"
#include "RTE_Device.h"
#if ((defined(RTE_Drivers_I2C1) || \
defined(RTE_Drivers_I2C2)) \
&& (RTE_I2C1 == 0) \
&& (RTE_I2C2 == 0))
#error "I2C not configured in RTE_Device.h!"
#endif
#define RCC_APB_I2C1_MASK RCC_APB1ENR_I2C1EN /* same for Clock/Reset */
#define RCC_APB_I2C2_MASK RCC_APB1ENR_I2C2EN /* same for Clock/Reset */
#define RCC_APB_I2C3_MASK RCC_APB1ENR_I2C3EN /* same for Clock/Reset */
/* I2C1 configuration definitions */
#if defined (RTE_I2C1) && (RTE_I2C1 == 1)
#if (((RTE_I2C1_RX_DMA != 0) && (RTE_I2C1_TX_DMA == 0)) || \
((RTE_I2C1_RX_DMA == 0) && (RTE_I2C1_TX_DMA != 0)))
#error "I2C1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h!"
#endif
#define USE_I2C1
#if (RTE_I2C1_RX_DMA == 1) && (RTE_I2C1_TX_DMA == 1)
#define USE_I2C1_DMA
/* Rx channel */
#define I2C1_RX_DMA_Instance DMAx_CHANNELy(RTE_I2C1_RX_DMA_NUMBER, RTE_I2C1_RX_DMA_CHANNEL)
#define I2C1_RX_DMA_Number RTE_I2C1_RX_DMA_NUMBER
#define I2C1_RX_DMA_Channel RTE_I2C1_RX_DMA_CHANNEL
#define I2C1_RX_DMA_Priority RTE_I2C1_RX_DMA_PRIORITY
#define I2C1_RX_DMA_Handler DMAx_CHANNELy_EVENT (RTE_I2C1_RX_DMA_NUMBER, RTE_I2C1_RX_DMA_CHANNEL)
/* Tx channel */
#define I2C1_TX_DMA_Instance DMAx_CHANNELy(RTE_I2C1_TX_DMA_NUMBER, RTE_I2C1_TX_DMA_CHANNEL)
#define I2C1_TX_DMA_Number RTE_I2C1_TX_DMA_NUMBER
#define I2C1_TX_DMA_Channel RTE_I2C1_TX_DMA_CHANNEL
#define I2C1_TX_DMA_Priority RTE_I2C1_TX_DMA_PRIORITY
#define I2C1_TX_DMA_Handler DMAx_CHANNELy_EVENT (RTE_I2C1_TX_DMA_NUMBER, RTE_I2C1_TX_DMA_CHANNEL)
#endif
#define I2C1_SCL_GPIOx RTE_I2C1_SCL_PORT
#define I2C1_SCL_GPIO_Pin RTE_I2C1_SCL_BIT
#define I2C1_SDA_GPIOx RTE_I2C1_SDA_PORT
#define I2C1_SDA_GPIO_Pin RTE_I2C1_SDA_BIT
#define I2C1_AF_REMAP RTE_I2C1_AF_REMAP
#endif
/* I2C2 configuration definitions */
#if defined (RTE_I2C2) && (RTE_I2C2 == 1)
#if !defined(I2C2)
#error "I2C2 not available for selected device!"
#endif
#if (((RTE_I2C2_RX_DMA != 0) && (RTE_I2C2_TX_DMA == 0)) || \
((RTE_I2C2_RX_DMA == 0) && (RTE_I2C2_TX_DMA != 0)))
#error "I2C2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h!"
#endif
#define USE_I2C2
#if (RTE_I2C2_RX_DMA == 1) && (RTE_I2C2_TX_DMA == 1)
#define USE_I2C2_DMA
/* Rx channel */
#define I2C2_RX_DMA_Instance DMAx_CHANNELy(RTE_I2C2_RX_DMA_NUMBER, RTE_I2C2_RX_DMA_CHANNEL)
#define I2C2_RX_DMA_Number RTE_I2C2_RX_DMA_NUMBER
#define I2C2_RX_DMA_Channel RTE_I2C2_RX_DMA_CHANNEL
#define I2C2_RX_DMA_Priority RTE_I2C2_RX_DMA_PRIORITY
#define I2C2_RX_DMA_Handler DMAx_CHANNELy_EVENT (RTE_I2C2_RX_DMA_NUMBER, RTE_I2C2_RX_DMA_CHANNEL)
/* Tx channel */
#define I2C2_TX_DMA_Instance DMAx_CHANNELy(RTE_I2C2_TX_DMA_NUMBER, RTE_I2C2_TX_DMA_CHANNEL)
#define I2C2_TX_DMA_Number RTE_I2C2_TX_DMA_NUMBER
#define I2C2_TX_DMA_Channel RTE_I2C2_TX_DMA_CHANNEL
#define I2C2_TX_DMA_Priority RTE_I2C2_TX_DMA_PRIORITY
#define I2C2_TX_DMA_Handler DMAx_CHANNELy_EVENT (RTE_I2C2_TX_DMA_NUMBER, RTE_I2C2_TX_DMA_CHANNEL)
#endif
#define I2C2_SCL_GPIOx RTE_I2C2_SCL_PORT
#define I2C2_SCL_GPIO_Pin RTE_I2C2_SCL_BIT
#define I2C2_SDA_GPIOx RTE_I2C2_SDA_PORT
#define I2C2_SDA_GPIO_Pin RTE_I2C2_SDA_BIT
#define I2C2_AF_REMAP RTE_I2C2_AF_REMAP
#endif
/* Current driver status flag definition */
#define I2C_INIT ((uint8_t)0x01) // I2C initialized
#define I2C_POWER ((uint8_t)0x02) // I2C powered on
#define I2C_SETUP ((uint8_t)0x04) // I2C configured
/* Transfer status flags definitions */
#define XFER_CTRL_XPENDING ((uint8_t)0x01) // Transfer pending
#define XFER_CTRL_RSTART ((uint8_t)0x02) // Generate repeated start and readdress
#define XFER_CTRL_ADDR_DONE ((uint8_t)0x04) // Addressing done
#define XFER_CTRL_DMA_DONE ((uint8_t)0x08) // DMA transfer done
#define XFER_CTRL_WAIT_BTF ((uint8_t)0x10) // Wait for byte transfer finished
#define XFER_CTRL_XACTIVE ((uint8_t)0x20) // Transfer active
/* DMA Information definitions */
typedef struct _I2C_DMA {
DMA_Channel_TypeDef *reg; // DMA register interface
uint8_t dma_num; // DMA number
uint8_t channel; // Channel number
uint8_t priority; // Channel priority
} const I2C_DMA;
/* I2C Input/Output Configuration */
typedef const struct _I2C_IO {
GPIO_TypeDef *scl_port; // SCL IO Port
GPIO_TypeDef *sda_port; // SDA IO Port
uint16_t scl_pin; // SCL IO Pin
uint16_t sda_pin; // SDA IO Pin
AFIO_REMAP remap;
} I2C_IO;
/* I2C Transfer Information (Run-Time) */
typedef struct _I2C_TRANSFER_INFO {
uint32_t num; // Number of data to transfer
uint32_t cnt; // Data transfer counter
uint8_t *data; // Data pointer
uint16_t addr; // Device address
uint8_t ctrl; // Transfer control flags
} I2C_TRANSFER_INFO;
/* I2C Information (Run-Time) */
typedef struct _I2C_INFO {
ARM_I2C_SignalEvent_t cb_event; // Event Callback
ARM_I2C_STATUS status; // Status flags
I2C_TRANSFER_INFO xfer; // Transfer information
uint8_t flags; // Current I2C state flags
} I2C_INFO;
/* I2C Resources definition */
typedef struct {
I2C_TypeDef *reg; // I2C peripheral register interface
I2C_DMA *dma_rx; // I2C DMA Configuration
I2C_DMA *dma_tx; // I2C DMA Configuration
I2C_IO io; // I2C Input/Output pins
IRQn_Type ev_irq_num; // I2C Event IRQ Number
IRQn_Type er_irq_num; // I2C Error IRQ Number
uint32_t apb_mask; // APB Clock/Reset register mask
I2C_INFO *info; // Run-Time information
} const I2C_RESOURCES;
#endif /* __I2C_STM32F10X_H */

View File

@ -0,0 +1,965 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2015 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 22. September 2015
* $Revision: V2.0
*
* Driver: Driver_MCI0
* Configured: via RTE_Device.h configuration file
* Project: MCI Driver for STMicroelectronics STM32F10x
* --------------------------------------------------------------------------
* Use the following configuration settings in the middleware component
* to connect to this driver.
*
* Configuration Setting Value
* --------------------- -----
* Connect to hardware via Driver_MCI# = 0
* -------------------------------------------------------------------------- */
/* History:
* Version 2.0
* Updated to CMSIS Driver API V2.02
* Version 1.2
* ST StdPeriph Drivers used for GPIO and DMA
* Version 1.1
* Based on API V1.10 (namespace prefix ARM_ added)
* Version 1.0
* Initial release
*/
#include "MCI_STM32F10x.h"
#define ARM_MCI_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,0) /* driver version */
/* Enable High Speed bus mode */
#if defined(MemoryCard_Bus_Mode_HS_Enable)
#define MCI_BUS_MODE_HS 1U
#else
#define MCI_BUS_MODE_HS 0U
#endif
/* Define Card Detect pin active state */
#if !defined(MemoryCard_CD_Pin_Active)
#define MemoryCard_CD_Pin_Active GPIO_PIN_RESET
#endif
/* Define Write Protect pin active state */
#if !defined(MemoryCard_WP_Pin_Active)
#define MemoryCard_WP_Pin_Active GPIO_PIN_SET
#endif
static MCI_INFO MCI;
/* IRQ Handler prototype */
void SDIO_IRQHandler (void);
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_MCI_API_VERSION,
ARM_MCI_DRV_VERSION
};
/* Driver Capabilities */
static const ARM_MCI_CAPABILITIES DriverCapabilities = {
MCI_CD_PIN, /* cd_state */
0U, /* cd_event */
MCI_WP_PIN, /* wp_state */
0U, /* vdd */
0U, /* vdd_1v8 */
0U, /* vccq */
0U, /* vccq_1v8 */
0U, /* vccq_1v2 */
MCI_BUS_WIDTH_4, /* data_width_4 */
MCI_BUS_WIDTH_8, /* data_width_8 */
0U, /* data_width_4_ddr */
0U, /* data_width_8_ddr */
MCI_BUS_MODE_HS, /* high_speed */
0U, /* uhs_signaling */
0U, /* uhs_tuning */
0U, /* uhs_sdr50 */
0U, /* uhs_sdr104 */
0U, /* uhs_ddr50 */
0U, /* uhs_driver_type_a */
0U, /* uhs_driver_type_c */
0U, /* uhs_driver_type_d */
1U, /* sdio_interrupt */
1U, /* read_wait */
0U, /* suspend_resume */
0U, /* mmc_interrupt */
0U, /* mmc_boot */
0U, /* rst_n */
0U, /* ccs */
0U /* ccs_timeout */
};
/**
\fn ARM_DRV_VERSION GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRV_VERSION
*/
static ARM_DRIVER_VERSION GetVersion (void) {
return DriverVersion;
}
/**
\fn ARM_MCI_CAPABILITIES MCI_GetCapabilities (void)
\brief Get driver capabilities.
\return \ref ARM_MCI_CAPABILITIES
*/
static ARM_MCI_CAPABILITIES GetCapabilities (void) {
return DriverCapabilities;
}
/**
\fn int32_t Initialize (ARM_MCI_SignalEvent_t cb_event)
\brief Initialize the Memory Card Interface
\param[in] cb_event Pointer to \ref ARM_MCI_SignalEvent
\return \ref execution_status
*/
static int32_t Initialize (ARM_MCI_SignalEvent_t cb_event) {
if (MCI.flags & MCI_INIT) { return ARM_DRIVER_OK; }
SystemCoreClockUpdate();
/* GPIO Ports Clock Enable */
GPIO_PortClock (GPIOC, true);
GPIO_PortClock (GPIOD, true);
/* Configure CMD, CK and D0 pins */
GPIO_PinConfigure(RTE_SDIO_CMD_PORT, RTE_SDIO_CMD_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_CK_PORT, RTE_SDIO_CK_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_D0_PORT, RTE_SDIO_D0_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
#if (MCI_BUS_WIDTH_4)
/* D[1:3] */
GPIO_PinConfigure(RTE_SDIO_D1_PORT, RTE_SDIO_D1_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_D2_PORT, RTE_SDIO_D2_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_D3_PORT, RTE_SDIO_D3_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
#endif
#if (MCI_BUS_WIDTH_8)
/* D[4:7] */
GPIO_PortClock (GPIOB, true);
GPIO_PinConfigure(RTE_SDIO_D4_PORT, RTE_SDIO_D4_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_D5_PORT, RTE_SDIO_D5_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_D6_PORT, RTE_SDIO_D6_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
GPIO_PinConfigure(RTE_SDIO_D7_PORT, RTE_SDIO_D7_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
#endif
/* Configure CD (Card Detect) Pin */
#if defined (MemoryCard_CD_Pin)
GPIO_PortClock (MemoryCard_CD_GPIOx, true);
GPIO_PinConfigure (MemoryCard_CD_GPIOx, MemoryCard_CD_GPIO_Pin, MemoryCard_CD_GPIO_PuPd,
GPIO_MODE_INPUT);
#endif
/* Configure WP (Write Protect) Pin */
#if defined (MemoryCard_WP_Pin)
GPIO_PortClock (MemoryCard_WP_GPIOx, true);
GPIO_PinConfigure (MemoryCard_WP_GPIOx, MemoryCard_WP_GPIO_Pin, MemoryCard_WP_GPIO_PuPd,
GPIO_MODE_INPUT);
#endif
/* Clear control structure */
memset (&MCI, 0, sizeof (MCI_INFO));
MCI.cb_event = cb_event;
MCI.flags = MCI_INIT;
return ARM_DRIVER_OK;
}
/**
\fn int32_t Uninitialize (void)
\brief De-initialize Memory Card Interface.
\return \ref execution_status
*/
static int32_t Uninitialize (void) {
MCI.flags = 0U;
/* Unconfigure CMD, CK and D0 pins */
GPIO_PinConfigure(RTE_SDIO_CMD_PORT, RTE_SDIO_CMD_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_CK_PORT, RTE_SDIO_CK_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_D0_PORT, RTE_SDIO_D0_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
#if (MCI_BUS_WIDTH_4)
/* Unconfigure D[1:3] */
GPIO_PinConfigure(RTE_SDIO_D1_PORT, RTE_SDIO_D1_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_D2_PORT, RTE_SDIO_D2_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_D3_PORT, RTE_SDIO_D3_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
#endif
#if (MCI_BUS_WIDTH_8)
/* Unconfigure D[4:7] */
GPIO_PinConfigure(RTE_SDIO_D4_PORT, RTE_SDIO_D4_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_D5_PORT, RTE_SDIO_D5_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_D6_PORT, RTE_SDIO_D6_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
GPIO_PinConfigure(RTE_SDIO_D7_PORT, RTE_SDIO_D7_PIN, GPIO_IN_ANALOG, GPIO_MODE_INPUT);
#endif
/* Unconfigure CD (Card Detect) Pin */
#if defined (MemoryCard_CD_Pin)
GPIO_PinConfigure (MemoryCard_CD_GPIOx, MemoryCard_CD_GPIO_Pin, GPIO_IN_ANALOG,
GPIO_MODE_INPUT);
#endif
/* Unconfigure WP (Write Protect) Pin */
#if defined (MemoryCard_WP_Pin)
GPIO_PinConfigure (MemoryCard_WP_GPIOx, MemoryCard_WP_GPIO_Pin, GPIO_IN_ANALOG,
GPIO_MODE_INPUT);
#endif
return ARM_DRIVER_OK;
}
/**
\fn int32_t PowerControl (ARM_POWER_STATE state)
\brief Control Memory Card Interface Power.
\param[in] state Power state \ref ARM_POWER_STATE
\return \ref execution_status
*/
static int32_t PowerControl (ARM_POWER_STATE state) {
int32_t status;
status = ARM_DRIVER_OK;
switch (state) {
case ARM_POWER_OFF:
/* Disable SDIO interrupts in NVIC */
NVIC_DisableIRQ (SDIO_IRQn);
/* Disable DMA channel */
DMA_ChannelUninitialize(SDIO_DMA_Number, SDIO_DMA_Channel);
/* SDIO peripheral clock disable */
RCC->AHBENR &= ~RCC_AHBENR_SDIOEN;
/* Clear status */
MCI.status.command_active = 0U;
MCI.status.command_timeout = 0U;
MCI.status.command_error = 0U;
MCI.status.transfer_active = 0U;
MCI.status.transfer_timeout = 0U;
MCI.status.transfer_error = 0U;
MCI.status.sdio_interrupt = 0U;
MCI.status.ccs = 0U;
MCI.flags &= ~MCI_POWER;
break;
case ARM_POWER_FULL:
if ((MCI.flags & MCI_INIT) == 0U) {
return ARM_DRIVER_ERROR;
}
if ((MCI.flags & MCI_POWER) != 0U) {
return ARM_DRIVER_OK;
}
/* Enable SDIO peripheral clock */
RCC->AHBENR |= RCC_AHBENR_SDIOEN;
/* Clear response and transfer variables */
MCI.response = NULL;
MCI.xfer.cnt = 0U;
/* Clear pending interrupts */
SDIO->ICR = SDIO_ICR_BIT_Msk;
/* Enable SDIO peripheral interrupts */
SDIO->MASK = SDIO_MASK_DATAENDIE |
SDIO_MASK_STBITERRIE |
SDIO_MASK_CMDSENTIE |
SDIO_MASK_CMDRENDIE |
SDIO_MASK_DTIMEOUTIE |
SDIO_MASK_CTIMEOUTIE |
SDIO_MASK_DCRCFAILIE |
SDIO_MASK_CCRCFAILIE ;
/* Set max data timeout */
SDIO->DTIMER = 0xFFFFFFFF;
/* Enable clock to the card (SDIO_CK) */
SDIO->POWER = SDIO_POWER_PWRCTRL_1 | SDIO_POWER_PWRCTRL_0;
/* Enable DMA channel */
DMA_ChannelInitialize (SDIO_DMA_Number, SDIO_DMA_Channel);
/* Enable SDIO interrupts in NVIC */
NVIC_ClearPendingIRQ(SDIO_IRQn);
NVIC_EnableIRQ(SDIO_IRQn);
MCI.flags |= MCI_POWER;
break;
case ARM_POWER_LOW:
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return status;
}
/**
\fn int32_t CardPower (uint32_t voltage)
\brief Set Memory Card supply voltage.
\param[in] voltage Memory Card supply voltage
\return \ref execution_status
*/
static int32_t CardPower (uint32_t voltage) {
if ((MCI.flags & MCI_POWER) == 0U) { return ARM_DRIVER_ERROR; }
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
/**
\fn int32_t ReadCD (void)
\brief Read Card Detect (CD) state.
\return 1:card detected, 0:card not detected, or error
*/
static int32_t ReadCD (void) {
if ((MCI.flags & MCI_POWER) == 0U) { return ARM_DRIVER_ERROR; }
/* Read CD (Card Detect) Pin */
#if defined (MemoryCard_CD_Pin)
if (GPIO_PinRead(MemoryCard_CD_GPIOx, MemoryCard_CD_GPIO_Pin) == MemoryCard_CD_Pin_Active) {
/* Card Detect switch is active */
return (1);
}
#endif
return (0);
}
/**
\fn int32_t ReadWP (void)
\brief Read Write Protect (WP) state.
\return 1:write protected, 0:not write protected, or error
*/
static int32_t ReadWP (void) {
if ((MCI.flags & MCI_POWER) == 0U) { return ARM_DRIVER_ERROR; }
/* Read WP (Write Protect) Pin */
#if defined (MemoryCard_WP_Pin)
if (GPIO_PinRead(MemoryCard_WP_GPIOx, MemoryCard_WP_GPIO_Pin) == MemoryCard_WP_Pin_Active) {
/* Write protect switch is active */
return (1);
}
#endif
return (0);
}
/**
\fn int32_t SendCommand (uint32_t cmd,
uint32_t arg,
uint32_t flags,
uint32_t *response)
\brief Send Command to card and get the response.
\param[in] cmd Memory Card command
\param[in] arg Command argument
\param[in] flags Command flags
\param[out] response Pointer to buffer for response
\return \ref execution_status
*/
static int32_t SendCommand (uint32_t cmd, uint32_t arg, uint32_t flags, uint32_t *response) {
uint32_t i, clkcr;
if (((flags & MCI_RESPONSE_EXPECTED_Msk) != 0U) && (response == NULL)) {
return ARM_DRIVER_ERROR_PARAMETER;
}
if ((MCI.flags & MCI_SETUP) == 0U) {
return ARM_DRIVER_ERROR;
}
if (MCI.status.command_active) {
return ARM_DRIVER_ERROR_BUSY;
}
MCI.status.command_active = 1U;
MCI.status.command_timeout = 0U;
MCI.status.command_error = 0U;
MCI.status.transfer_timeout = 0U;
MCI.status.transfer_error = 0U;
MCI.status.ccs = 0U;
if (flags & ARM_MCI_CARD_INITIALIZE) {
clkcr = SDIO->CLKCR;
if (((clkcr & SDIO_CLKCR_CLKEN) == 0) || ((clkcr & SDIO_CLKCR_PWRSAV) != 0)) {
SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_PWRSAV) | SDIO_CLKCR_CLKEN;
i = SystemCoreClock;
for (i = (i/5000000U)*1000U; i; i--) {
; /* Wait for approximate 1000us */
}
SDIO->CLKCR = clkcr;
}
}
/* Set command register value */
cmd = SDIO_CMD_CPSMEN | (cmd & 0xFFU);
MCI.response = response;
MCI.flags &= ~(MCI_RESP_CRC | MCI_RESP_LONG);
switch (flags & ARM_MCI_RESPONSE_Msk) {
case ARM_MCI_RESPONSE_NONE:
/* No response expected (wait CMDSENT) */
break;
case ARM_MCI_RESPONSE_SHORT:
case ARM_MCI_RESPONSE_SHORT_BUSY:
/* Short response expected (wait CMDREND or CCRCFAIL) */
cmd |= SDIO_CMD_WAITRESP_0;
break;
case ARM_MCI_RESPONSE_LONG:
MCI.flags |= MCI_RESP_LONG;
/* Long response expected (wait CMDREND or CCRCFAIL) */
cmd |= SDIO_CMD_WAITRESP_1 | SDIO_CMD_WAITRESP_0;
break;
default:
return ARM_DRIVER_ERROR;
}
if (flags & ARM_MCI_RESPONSE_CRC) {
MCI.flags |= MCI_RESP_CRC;
}
if (flags & ARM_MCI_TRANSFER_DATA) {
MCI.flags |= MCI_DATA_XFER;
}
/* Clear all interrupt flags */
SDIO->ICR = SDIO_ICR_BIT_Msk;
/* Send the command */
SDIO->ARG = arg;
SDIO->CMD = cmd;
return ARM_DRIVER_OK;
}
/**
\fn int32_t SetupTransfer (uint8_t *data,
uint32_t block_count,
uint32_t block_size,
uint32_t mode)
\brief Setup read or write transfer operation.
\param[in,out] data Pointer to data block(s) to be written or read
\param[in] block_count Number of blocks
\param[in] block_size Size of a block in bytes
\param[in] mode Transfer mode
\return \ref execution_status
*/
static int32_t SetupTransfer (uint8_t *data, uint32_t block_count, uint32_t block_size, uint32_t mode) {
uint32_t sz, cnt, cfg, dctrl;
if ((data == NULL) || (block_count == 0U) || (block_size == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
if ((MCI.flags & MCI_SETUP) == 0U) {
return ARM_DRIVER_ERROR;
}
if (MCI.status.transfer_active) {
return ARM_DRIVER_ERROR_BUSY;
}
MCI.xfer.buf = data;
MCI.xfer.cnt = block_count * block_size;
cnt = MCI.xfer.cnt;
if (cnt > 0xFFFFU) {
cnt = 0xFFFFU;
}
MCI.xfer.cnt -= cnt;
MCI.xfer.buf += cnt;
dctrl = 0U;
if ((mode & ARM_MCI_TRANSFER_WRITE) == 0) {
/* Direction: From card to controller */
MCI.flags |= MCI_DATA_READ;
dctrl |= SDIO_DCTRL_DTDIR;
}
else {
MCI.flags &= ~MCI_DATA_READ;
}
if (mode & ARM_MCI_TRANSFER_STREAM) {
/* Stream or SDIO multibyte data transfer enable */
dctrl |= SDIO_DCTRL_DTMODE;
}
/* Set data block size */
if (block_size == 512U) {
sz = 9U;
}
else {
if (block_size > 16384U) {
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
for (sz = 0U; sz < 14U; sz++) {
if (block_size & (1UL << sz)) {
break;
}
}
}
/* Configure and enable DMA channel */
cfg = DMA_PERIPHERAL_TO_MEMORY |
(SDIO_DMA_Priority << DMA_PRIORITY_POS) |
DMA_MEMORY_DATA_32BIT |
DMA_PERIPHERAL_DATA_32BIT |
DMA_MEMORY_INCREMENT |
DMA_TRANSFER_ERROR_INTERRUPT |
DMA_TRANSFER_COMPLETE_INTERRUPT ;
if (mode & ARM_MCI_TRANSFER_WRITE) {
cfg |= DMA_READ_MEMORY;
}
DMA_ChannelConfigure(SDIO_DMA_Instance, cfg, (uint32_t)&(SDIO->FIFO), (uint32_t)data, cnt/4);
DMA_ChannelEnable (SDIO_DMA_Instance);
MCI.dlen = cnt;
MCI.dctrl = dctrl | (sz << 4) | SDIO_DCTRL_DMAEN;
return (ARM_DRIVER_OK);
}
/**
\fn int32_t AbortTransfer (void)
\brief Abort current read/write data transfer.
\return \ref execution_status
*/
static int32_t AbortTransfer (void) {
int32_t status;
uint32_t mask;
if ((MCI.flags & MCI_SETUP) == 0U) { return ARM_DRIVER_ERROR; }
status = ARM_DRIVER_OK;
/* Disable SDIO interrupts */
mask = SDIO->MASK;
SDIO->MASK = 0U;
/* Disable DMA and clear data transfer bit */
SDIO->DCTRL &= ~(SDIO_DCTRL_DMAEN | SDIO_DCTRL_DTEN);
DMA_ChannelDisable (SDIO_DMA_Instance);
/* Clear SDIO FIFO */
while (SDIO->FIFOCNT) {
SDIO->FIFO;
}
MCI.status.command_active = 0U;
MCI.status.transfer_active = 0U;
MCI.status.sdio_interrupt = 0U;
MCI.status.ccs = 0U;
/* Clear pending SDIO interrupts */
SDIO->ICR = SDIO_ICR_BIT_Msk;
/* Enable SDIO interrupts */
SDIO->MASK = mask;
return status;
}
/**
\fn int32_t Control (uint32_t control, uint32_t arg)
\brief Control MCI Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\return \ref execution_status
*/
static int32_t Control (uint32_t control, uint32_t arg) {
uint32_t val, clkdiv, bps;
if ((MCI.flags & MCI_POWER) == 0U) { return ARM_DRIVER_ERROR; }
switch (control) {
case ARM_MCI_BUS_SPEED:
/* Determine clock divider and set bus speed */
bps = arg;
if ((bps < SDIOCLK) || (MCI_BUS_MODE_HS == 0U)) {
/* bps = SDIOCLK / (clkdiv + 2) */
clkdiv = (SDIOCLK + bps - 1U) / bps;
if (clkdiv < 2) { clkdiv = 0U; }
else { clkdiv -= 2U; }
if (clkdiv > SDIO_CLKCR_CLKDIV) {
clkdiv = SDIO_CLKCR_CLKDIV;
}
SDIO->CLKCR = (SDIO->CLKCR & ~(SDIO_CLKCR_CLKDIV | SDIO_CLKCR_BYPASS)) |
SDIO_CLKCR_CLKEN | clkdiv;
bps = SDIOCLK / (clkdiv + 2U);
}
else {
/* Max output clock is SDIOCLK */
SDIO->CLKCR |= SDIO_CLKCR_BYPASS | SDIO_CLKCR_CLKEN;
bps = SDIOCLK;
}
for (val = (SDIOCLK/5000000U)*20U; val; val--) {
; /* Wait a bit to get stable clock */
}
/* Bus speed configured */
MCI.flags |= MCI_SETUP;
return ((int32_t)bps);
case ARM_MCI_BUS_SPEED_MODE:
switch (arg) {
case ARM_MCI_BUS_DEFAULT_SPEED:
/* Speed mode up to 25MHz */
SDIO->CLKCR &= ~SDIO_CLKCR_NEGEDGE;
break;
case ARM_MCI_BUS_HIGH_SPEED:
/* Speed mode up to 50MHz */
/* Errata: configuration with the NEGEDGE bit set should not be used. */
break;
default: return ARM_DRIVER_ERROR_UNSUPPORTED;
}
break;
case ARM_MCI_BUS_CMD_MODE:
switch (arg) {
case ARM_MCI_BUS_CMD_OPEN_DRAIN:
/* Configure command line in open-drain mode */
GPIO_PinConfigure(RTE_SDIO_CMD_PORT, RTE_SDIO_CMD_PIN, GPIO_AF_OPENDRAIN,
GPIO_MODE_OUT50MHZ);
break;
case ARM_MCI_BUS_CMD_PUSH_PULL:
/* Configure command line in push-pull mode */
GPIO_PinConfigure(RTE_SDIO_CMD_PORT, RTE_SDIO_CMD_PIN, GPIO_AF_PUSHPULL,
GPIO_MODE_OUT50MHZ);
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
break;
case ARM_MCI_BUS_DATA_WIDTH:
switch (arg) {
case ARM_MCI_BUS_DATA_WIDTH_1:
SDIO->CLKCR &= ~SDIO_CLKCR_WIDBUS;
break;
case ARM_MCI_BUS_DATA_WIDTH_4:
SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_WIDBUS) | SDIO_CLKCR_WIDBUS_0;
break;
case ARM_MCI_BUS_DATA_WIDTH_8:
SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_WIDBUS) | SDIO_CLKCR_WIDBUS_1;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
break;
case ARM_MCI_CONTROL_CLOCK_IDLE:
if (arg) {
/* Clock generation enabled when idle */
SDIO->CLKCR &= ~SDIO_CLKCR_PWRSAV;
}
else {
/* Clock generation disabled when idle */
SDIO->CLKCR |= SDIO_CLKCR_PWRSAV;
}
break;
case ARM_MCI_DATA_TIMEOUT:
SDIO->DTIMER = arg;
break;
case ARM_MCI_MONITOR_SDIO_INTERRUPT:
MCI.status.sdio_interrupt = 0U;
SDIO->MASK |= SDIO_MASK_SDIOITIE;
break;
case ARM_MCI_CONTROL_READ_WAIT:
if (arg) {
/* Assert read wait */
MCI.flags |= MCI_READ_WAIT;
}
else {
/* Clear read wait */
MCI.flags &= ~MCI_READ_WAIT;
SDIO->DCTRL &= ~SDIO_DCTRL_RWSTOP;
}
break;
default: return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
/**
\fn ARM_MCI_STATUS GetStatus (void)
\brief Get MCI status.
\return MCI status \ref ARM_MCI_STATUS
*/
static ARM_MCI_STATUS GetStatus (void) {
return MCI.status;
}
/* SDIO IRQ Handler */
void SDIO_IRQHandler (void) {
uint32_t sta, icr, event, mask;
event = 0U;
icr = 0U;
/* Read SDIO interrupt status */
sta = SDIO->STA;
if (sta & SDIO_STA_ERR_BIT_Msk) {
/* Check error interrupts */
if (sta & SDIO_STA_CCRCFAIL) {
icr |= SDIO_ICR_CCRCFAILC;
/* Command response CRC check failed */
if (MCI.flags & MCI_RESP_CRC) {
MCI.status.command_error = 1U;
event |= ARM_MCI_EVENT_COMMAND_ERROR;
}
else {
/* Ignore CRC error and read the response */
sta |= SDIO_STA_CMDREND;
}
}
if (sta & SDIO_STA_DCRCFAIL) {
icr |= SDIO_ICR_DCRCFAILC;
/* Data block CRC check failed */
MCI.status.transfer_error = 1U;
event |= ARM_MCI_EVENT_TRANSFER_ERROR;
}
if (sta & SDIO_STA_CTIMEOUT) {
icr |= SDIO_ICR_CTIMEOUTC;
/* Command response timeout */
MCI.status.command_timeout = 1U;
event |= ARM_MCI_EVENT_COMMAND_TIMEOUT;
}
if (sta & SDIO_STA_DTIMEOUT) {
icr |= SDIO_ICR_DTIMEOUTC;
/* Data timeout */
MCI.status.transfer_timeout = 1U;
event |= ARM_MCI_EVENT_TRANSFER_TIMEOUT;
}
if (sta & SDIO_STA_STBITERR) {
icr |= SDIO_ICR_STBITERRC;
/* Start bit not detected on all data signals */
event |= ARM_MCI_EVENT_TRANSFER_ERROR;
}
}
if (sta & SDIO_STA_CMDREND) {
icr |= SDIO_ICR_CMDRENDC;
/* Command response received */
event |= ARM_MCI_EVENT_COMMAND_COMPLETE;
if (MCI.response) {
/* Read response registers */
if (MCI.flags & MCI_RESP_LONG) {
MCI.response[0] = SDIO->RESP4;
MCI.response[1] = SDIO->RESP3;
MCI.response[2] = SDIO->RESP2;
MCI.response[3] = SDIO->RESP1;
}
else {
MCI.response[0] = SDIO->RESP1;
}
}
if (MCI.flags & MCI_DATA_XFER) {
MCI.flags &= ~MCI_DATA_XFER;
if (MCI.flags & MCI_READ_WAIT) {
MCI.dctrl |= SDIO_DCTRL_RWSTART;
}
/* Start data transfer */
SDIO->DLEN = MCI.dlen;
SDIO->DCTRL = MCI.dctrl | SDIO_DCTRL_DTEN;
MCI.status.transfer_active = 1U;
}
}
if (sta & SDIO_STA_CMDSENT) {
icr |= SDIO_ICR_CMDSENTC;
/* Command sent (no response required) */
event |= ARM_MCI_EVENT_COMMAND_COMPLETE;
}
if (sta & SDIO_STA_DATAEND) {
icr |= SDIO_ICR_DATAENDC;
/* Data end (DCOUNT is zero) */
if ((MCI.flags & MCI_DATA_READ) == 0) {
/* Write transfer */
SDIO->MASK |= SDIO_MASK_DBCKENDIE;
}
}
if (sta & SDIO_STA_DBCKEND) {
icr |= SDIO_ICR_DBCKENDC;
/* Data block sent/received (CRC check passed) */
if ((MCI.flags & MCI_DATA_READ) == 0) {
/* Write transfer */
if (MCI.xfer.cnt == 0) {
event |= ARM_MCI_EVENT_TRANSFER_COMPLETE;
}
}
SDIO->MASK &= ~SDIO_MASK_DBCKENDIE;
}
if (sta & SDIO_STA_SDIOIT) {
icr |= SDIO_ICR_SDIOITC;
/* Disable interrupt (must be re-enabled using Control) */
SDIO->MASK &= SDIO_MASK_SDIOITIE;
event |= ARM_MCI_EVENT_SDIO_INTERRUPT;
}
/* Clear processed interrupts */
SDIO->ICR = icr;
if (event) {
/* Check for transfer events */
mask = ARM_MCI_EVENT_TRANSFER_ERROR |
ARM_MCI_EVENT_TRANSFER_TIMEOUT |
ARM_MCI_EVENT_TRANSFER_COMPLETE;
if (event & mask) {
MCI.status.transfer_active = 0U;
if (MCI.cb_event) {
if (event & ARM_MCI_EVENT_TRANSFER_ERROR) {
(MCI.cb_event)(ARM_MCI_EVENT_TRANSFER_ERROR);
}
else if (event & ARM_MCI_EVENT_TRANSFER_TIMEOUT) {
(MCI.cb_event)(ARM_MCI_EVENT_TRANSFER_TIMEOUT);
}
else {
(MCI.cb_event)(ARM_MCI_EVENT_TRANSFER_COMPLETE);
}
}
}
/* Check for command events */
mask = ARM_MCI_EVENT_COMMAND_ERROR |
ARM_MCI_EVENT_COMMAND_TIMEOUT |
ARM_MCI_EVENT_COMMAND_COMPLETE;
if (event & mask) {
MCI.status.command_active = 0U;
if (MCI.cb_event) {
if (event & ARM_MCI_EVENT_COMMAND_ERROR) {
(MCI.cb_event)(ARM_MCI_EVENT_COMMAND_ERROR);
}
else if (event & ARM_MCI_EVENT_COMMAND_TIMEOUT) {
(MCI.cb_event)(ARM_MCI_EVENT_COMMAND_TIMEOUT);
}
else {
(MCI.cb_event)(ARM_MCI_EVENT_COMMAND_COMPLETE);
}
}
}
/* Check for SDIO INT event */
if (event & ARM_MCI_EVENT_SDIO_INTERRUPT) {
MCI.status.sdio_interrupt = 1U;
if (MCI.cb_event) {
(MCI.cb_event)(ARM_MCI_EVENT_SDIO_INTERRUPT);
}
}
}
}
/* DMA event handler */
void SDIO_DMA_Handler (uint32_t event) {
uint32_t evt = 0;
/* Disable DMA channel */
DMA_ChannelDisable(SDIO_DMA_Instance);
if (event & DMA_TRANSFER_COMPLETE_INTERRUPT) {
if (MCI.flags & MCI_DATA_READ) {
evt = ARM_MCI_EVENT_TRANSFER_COMPLETE;
MCI.status.transfer_active = 0U;
}
}
if (event & DMA_CHANNEL_TRANSFER_ERROR) {
evt = ARM_MCI_EVENT_TRANSFER_COMPLETE;
}
if (evt && MCI.cb_event) {
(MCI.cb_event)(evt);
}
}
/* MCI Driver Control Block */
ARM_DRIVER_MCI Driver_MCI0 = {
GetVersion,
GetCapabilities,
Initialize,
Uninitialize,
PowerControl,
CardPower,
ReadCD,
ReadWP,
SendCommand,
SetupTransfer,
AbortTransfer,
Control,
GetStatus
};

View File

@ -0,0 +1,177 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2015 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 22. September 2015
* $Revision: V2.0
*
* Project: MCI Driver Definitions for STMicroelectronics STM32F10x
* -------------------------------------------------------------------------- */
#ifndef __MCI_STM32F10X_H
#define __MCI_STM32F10X_H
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "DMA_STM32F10x.h"
#include "Driver_MCI.h"
#include "RTE_Components.h"
#include "RTE_Device.h"
#include <string.h>
#if (defined(RTE_Drivers_MCI0) && (RTE_SDIO == 0))
#error "SDIO not configured in RTE_Device.h!"
#endif
/* SDIO DMA */
#define SDIO_DMA_Instance DMAx_CHANNELy(RTE_SDIO_DMA_NUMBER, RTE_SDIO_DMA_CHANNEL)
#define SDIO_DMA_Number RTE_SDIO_DMA_NUMBER
#define SDIO_DMA_Channel RTE_SDIO_DMA_CHANNEL
#define SDIO_DMA_Priority RTE_SDIO_DMA_PRIORITY
#define SDIO_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SDIO_DMA_NUMBER, RTE_SDIO_DMA_CHANNEL)
#if (RTE_SDIO_BUS_WIDTH_4)
#define SDIO_D0_Pin 1
#define SDIO_D1_Pin 1
#define SDIO_D2_Pin 1
#define SDIO_D3_Pin 1
#endif
#if (RTE_SDIO_BUS_WIDTH_8)
#define SDIO_D4_Pin 1
#define SDIO_D5_Pin 1
#define SDIO_D6_Pin 1
#define SDIO_D7_Pin 1
#endif
#if (RTE_SDIO_CD_EN)
#define MemoryCard_CD_Pin 1
#define MemoryCard_CD_GPIOx RTE_SDIO_CD_PORT
#define MemoryCard_CD_GPIO_Pin RTE_SDIO_CD_PIN
#define MemoryCard_CD_GPIO_PuPd ((RTE_SDIO_CD_ACTIVE == 0) ? GPIO_IN_PULL_UP : GPIO_IN_PULL_DOWN)
#define MemoryCard_CD_Pin_Active ((RTE_SDIO_CD_ACTIVE == 0) ? 0 : 1)
#endif
#if (RTE_SDIO_WP_EN)
#define MemoryCard_WP_Pin 1
#define MemoryCard_WP_GPIOx RTE_SDIO_WP_PORT
#define MemoryCard_WP_GPIO_Pin RTE_SDIO_WP_PIN
#define MemoryCard_WP_GPIO_PuPd ((RTE_SDIO_WP_ACTIVE == 0) ? GPIO_IN_PULL_UP : GPIO_IN_PULL_DOWN)
#define MemoryCard_WP_Pin_Active ((RTE_SDIO_WP_ACTIVE == 0) ? 0 : 1)
#endif
/* Define 4-bit data bus width */
#if defined(SDIO_D0_Pin) && defined(SDIO_D1_Pin) && defined(SDIO_D2_Pin) && defined(SDIO_D3_Pin)
#define MCI_BUS_WIDTH_4 1U
#else
#define MCI_BUS_WIDTH_4 0U
#endif
/* Define 8-bit data bus width */
#if defined(SDIO_D0_Pin) && defined(SDIO_D1_Pin) && defined(SDIO_D2_Pin) && defined(SDIO_D3_Pin) && \
defined(SDIO_D4_Pin) && defined(SDIO_D5_Pin) && defined(SDIO_D6_Pin) && defined(SDIO_D7_Pin)
#define MCI_BUS_WIDTH_8 1U
#else
#define MCI_BUS_WIDTH_8 0U
#endif
/* Define Card Detect pin existence */
#if defined(MemoryCard_CD_Pin)
#define MCI_CD_PIN 1U
#else
#define MCI_CD_PIN 0U
#endif
/* Define Write Protect pin existence */
#if defined(MemoryCard_WP_Pin)
#define MCI_WP_PIN 1U
#else
#define MCI_WP_PIN 0U
#endif
/* SDIO Adapter Clock definition */
#define SDIOCLK (uint32_t)RTE_HCLK /* SDIO adapter clock */
#ifndef SDIO_MASK_STBITERRIE
#define SDIO_MASK_STBITERRIE 0U
#endif
#ifndef SDIO_STA_STBITERR
#define SDIO_STA_STBITERR 0U
#endif
#ifndef SDIO_ICR_STBITERRC
#define SDIO_ICR_STBITERRC 0U
#endif
/* Interrupt clear Mask */
#define SDIO_ICR_BIT_Msk (SDIO_ICR_CCRCFAILC | \
SDIO_ICR_DCRCFAILC | \
SDIO_ICR_CTIMEOUTC | \
SDIO_ICR_DTIMEOUTC | \
SDIO_ICR_TXUNDERRC | \
SDIO_ICR_RXOVERRC | \
SDIO_ICR_CMDRENDC | \
SDIO_ICR_CMDSENTC | \
SDIO_ICR_DATAENDC | \
SDIO_ICR_STBITERRC | \
SDIO_ICR_DBCKENDC | \
SDIO_ICR_SDIOITC)
/* Error interrupt mask */
#define SDIO_STA_ERR_BIT_Msk (SDIO_STA_CCRCFAIL | \
SDIO_STA_DCRCFAIL | \
SDIO_STA_CTIMEOUT | \
SDIO_STA_DTIMEOUT | \
SDIO_STA_STBITERR)
/* Driver flag definitions */
#define MCI_INIT ((uint8_t)0x01) /* MCI initialized */
#define MCI_POWER ((uint8_t)0x02) /* MCI powered on */
#define MCI_SETUP ((uint8_t)0x04) /* MCI configured */
#define MCI_RESP_LONG ((uint8_t)0x08) /* Long response expected */
#define MCI_RESP_CRC ((uint8_t)0x10) /* Check response CRC error */
#define MCI_DATA_XFER ((uint8_t)0x20) /* Transfer data */
#define MCI_DATA_READ ((uint8_t)0x40) /* Read transfer */
#define MCI_READ_WAIT ((uint8_t)0x80) /* Read wait operation start */
#define MCI_RESPONSE_EXPECTED_Msk (ARM_MCI_RESPONSE_SHORT | \
ARM_MCI_RESPONSE_SHORT_BUSY | \
ARM_MCI_RESPONSE_LONG)
/* MCI Transfer Information Definition */
typedef struct _MCI_XFER {
uint8_t *buf; /* Data buffer */
uint32_t cnt; /* Data bytes to transfer */
} MCI_XFER;
/* MCI Driver State Definition */
typedef struct _MCI_INFO {
ARM_MCI_SignalEvent_t cb_event; /* Driver event callback function */
ARM_MCI_STATUS status; /* Driver status */
uint32_t *response; /* Pointer to response buffer */
MCI_XFER xfer; /* Data transfer description */
uint8_t volatile flags; /* Driver state flags */
uint32_t dctrl; /* Data control register value */
uint32_t dlen; /* Data length register value */
} MCI_INFO;
#endif /* __MCI_STM32F10X_H */

View File

@ -0,0 +1,200 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2017 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 19. September 2017
* $Revision: V2.3
*
* Project: OTG Full/Low-Speed Common Driver for ST STM32F1xx
* -------------------------------------------------------------------------- */
/* History:
* Version 2.3
* Removed unnecessary include of cmsis_os.h
* Version 2.2
* Corrected over-current pin configuration
* Version 2.1
* Added configuration for USB Device VBUS pin so connection/disconnection of
* USB cable can be detected when device is self-powered
* Version 2.0
* Based on API V2.01
* Version 1.03
* Based on API V1.10 (namespace prefix ARM_ added)
* Version 1.00
* Initial release
*/
#include <stdint.h>
#include <string.h>
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "OTG_STM32F10x_cl.h"
#include "Driver_USBH.h"
#include "Driver_USBD.h"
extern void USBH_FS_IRQ (uint32_t gintsts);
extern void USBD_FS_IRQ (uint32_t gintsts);
uint8_t otg_fs_role = ARM_USB_ROLE_NONE;
// Common IRQ Routine **********************************************************
/**
\fn void OTG_FS_IRQHandler (void)
\brief USB Interrupt Routine (IRQ).
*/
void OTG_FS_IRQHandler (void) {
uint32_t gintsts;
gintsts = OTG_FS->GINTSTS & OTG_FS->GINTMSK;
#if (defined(MX_USB_OTG_FS_HOST) && defined(MX_USB_OTG_FS_DEVICE))
switch (otg_fs_role) {
#ifdef MX_USB_OTG_FS_HOST
case ARM_USB_ROLE_HOST:
USBH_FS_IRQ (gintsts);
break;
#endif
#ifdef MX_USB_OTG_FS_DEVICE
case ARM_USB_ROLE_DEVICE:
USBD_FS_IRQ (gintsts);
break;
#endif
default:
break;
}
#else
#ifdef MX_USB_OTG_FS_HOST
USBH_FS_IRQ (gintsts);
#else
USBD_FS_IRQ (gintsts);
#endif
#endif
}
// Public Functions ************************************************************
/**
\fn void OTG_FS_PinsConfigure (uint8_t pins_mask)
\brief Configure single or multiple USB Pin(s).
\param[in] Mask of pins to be configured (possible masking values:
USB_PIN_DP, USB_PIN_DM, USB_PIN_VBUS, USB_PIN_OC, USB_PIN_ID)
*/
void OTG_FS_PinsConfigure (uint8_t pins_mask) {
#ifdef MX_USB_OTG_FS_VBUS_Power_Pin // Host VBUS power driving pin (output)
if ((pins_mask & ARM_USB_PIN_VBUS) != 0U) {
if (otg_fs_role == ARM_USB_ROLE_DEVICE) {
GPIO_PortClock (GPIOA, true);
GPIO_PinConfigure(GPIOA, 9, GPIO_IN_FLOATING, GPIO_MODE_INPUT);
}
if (otg_fs_role == ARM_USB_ROLE_HOST) {
GPIO_PortClock (MX_USB_OTG_FS_VBUS_Power_GPIOx, true);
#if (USB_OTG_FS_VBUS_Power_Pin_Active == 0)
GPIO_PinWrite (MX_USB_OTG_FS_VBUS_Power_GPIOx, MX_USB_OTG_FS_VBUS_Power_GPIO_Pin, 1U);
#else
GPIO_PinWrite (MX_USB_OTG_FS_VBUS_Power_GPIOx, MX_USB_OTG_FS_VBUS_Power_GPIO_Pin, 0U);
#endif
GPIO_PinConfigure(MX_USB_OTG_FS_VBUS_Power_GPIOx, MX_USB_OTG_FS_VBUS_Power_GPIO_Pin, GPIO_OUT_PUSH_PULL, GPIO_MODE_OUT10MHZ);
}
}
#endif
#ifdef MX_USB_OTG_FS_Overcurrent_Pin // Host overcurrent sensing pin (input)
if ((pins_mask & ARM_USB_PIN_OC) != 0U) {
if (otg_fs_role == ARM_USB_ROLE_HOST) {
GPIO_PortClock (MX_USB_OTG_FS_Overcurrent_GPIOx, true);
GPIO_PinConfigure(MX_USB_OTG_FS_Overcurrent_GPIOx, MX_USB_OTG_FS_Overcurrent_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT);
}
}
#endif
}
/**
\fn void OTG_FS_PinsUnconfigure (uint8_t pins_mask)
\brief Unconfigure to reset settings single or multiple USB Pin(s).
\param[in] Mask of pins to be unconfigured (possible masking values:
USB_PIN_DP, USB_PIN_DM, USB_PIN_VBUS, USB_PIN_OC, USB_PIN_ID)
*/
void OTG_FS_PinsUnconfigure (uint8_t pins_mask) {
#ifdef MX_USB_OTG_FS_VBUS_Power_Pin
if ((pins_mask & ARM_USB_PIN_VBUS) != 0U) {
if (otg_fs_role == ARM_USB_ROLE_HOST) {
GPIO_PortClock (MX_USB_OTG_FS_VBUS_Power_GPIOx, true);
GPIO_PinConfigure(MX_USB_OTG_FS_VBUS_Power_GPIOx, MX_USB_OTG_FS_VBUS_Power_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT);
}
}
#endif
#ifdef MX_USB_OTG_FS_Overcurrent_Pin
if ((pins_mask & ARM_USB_PIN_OC) != 0U) {
if (otg_fs_role == ARM_USB_ROLE_HOST) {
GPIO_PortClock (MX_USB_OTG_FS_Overcurrent_GPIOx, true);
GPIO_PinConfigure(MX_USB_OTG_FS_Overcurrent_GPIOx, MX_USB_OTG_FS_Overcurrent_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT);
}
}
#endif
}
/**
\fn void OTG_FS_PinVbusOnOff (bool state)
\brief Drive VBUS Pin On/Off.
\param[in] state State On/Off (true = On, false = Off)
*/
void OTG_FS_PinVbusOnOff (bool state) {
#ifdef MX_USB_OTG_FS_VBUS_Power_Pin
if (otg_fs_role == ARM_USB_ROLE_HOST) {
#if (USB_OTG_FS_VBUS_Power_Pin_Active == 0)
GPIO_PinWrite (MX_USB_OTG_FS_VBUS_Power_GPIOx, MX_USB_OTG_FS_VBUS_Power_GPIO_Pin,((state == true) ? 0U : 1U));
#else
GPIO_PinWrite (MX_USB_OTG_FS_VBUS_Power_GPIOx, MX_USB_OTG_FS_VBUS_Power_GPIO_Pin,((state == true) ? 1U : 0U));
#endif
}
#endif
}
/**
\fn bool OTG_FS_PinGetOC (void)
\brief Get state of Overcurrent Pin.
\return overcurrent state (true = Overcurrent active, false = No overcurrent)
*/
bool OTG_FS_PinGetOC (void) {
#ifdef MX_USB_OTG_FS_Overcurrent_Pin
if (otg_fs_role == ARM_USB_ROLE_HOST) {
#if (USB_OTG_FS_Overcurrent_Pin_Active == 0)
return ((GPIO_PinRead (MX_USB_OTG_FS_Overcurrent_GPIOx, MX_USB_OTG_FS_Overcurrent_GPIO_Pin) == 0U) ? true : false);
#else
return ((GPIO_PinRead (MX_USB_OTG_FS_Overcurrent_GPIOx, MX_USB_OTG_FS_Overcurrent_GPIO_Pin) == 1U) ? true : false);
#endif
}
return false;
#else
return false;
#endif
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,332 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2015 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 29. August 2016
* $Revision: V2.2
*
* Project: SPI Driver definitions for STMicroelectronics STM32F10x
* -------------------------------------------------------------------------- */
#ifndef __SPI_STM32F10X_H
#define __SPI_STM32F10X_H
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "DMA_STM32F10x.h"
#include "Driver_SPI.h"
#include "RTE_Components.h"
#include "RTE_Device.h"
#if ((defined(RTE_Drivers_SPI1) || \
defined(RTE_Drivers_SPI2) || \
defined(RTE_Drivers_SPI3)) \
&& (RTE_SPI1 == 0) \
&& (RTE_SPI2 == 0) \
&& (RTE_SPI3 == 0))
#error "SPI not configured in RTE_Device.h!"
#endif
// SPI1 configuration definitions
#if (RTE_SPI1 == 1)
#define MX_SPI1
#if (RTE_SPI1_RX_DMA == 1)
#define MX_SPI1_RX_DMA_Instance DMAx_CHANNELy(RTE_SPI1_RX_DMA_NUMBER, RTE_SPI1_RX_DMA_CHANNEL)
#define MX_SPI1_RX_DMA_Number RTE_SPI1_RX_DMA_NUMBER
#define MX_SPI1_RX_DMA_Channel RTE_SPI1_RX_DMA_CHANNEL
#define MX_SPI1_RX_DMA_Priority RTE_SPI1_RX_DMA_PRIORITY
#define SPI1_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SPI1_RX_DMA_NUMBER, RTE_SPI1_RX_DMA_CHANNEL)
#endif
#if (RTE_SPI1_TX_DMA == 1)
#define MX_SPI1_TX_DMA_Instance DMAx_CHANNELy(RTE_SPI1_TX_DMA_NUMBER, RTE_SPI1_TX_DMA_CHANNEL)
#define MX_SPI1_TX_DMA_Number RTE_SPI1_TX_DMA_NUMBER
#define MX_SPI1_TX_DMA_Channel RTE_SPI1_TX_DMA_CHANNEL
#define MX_SPI1_TX_DMA_Priority RTE_SPI1_TX_DMA_PRIORITY
#define SPI1_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SPI1_TX_DMA_NUMBER, RTE_SPI1_TX_DMA_CHANNEL)
#endif
#if (RTE_SPI1_MISO == 1)
#define MX_SPI1_MISO_Pin 1U
#define MX_SPI1_MISO_GPIOx RTE_SPI1_MISO_PORT
#define MX_SPI1_MISO_GPIO_Pin RTE_SPI1_MISO_BIT
#endif
#if (RTE_SPI1_MOSI == 1)
#define MX_SPI1_MOSI_Pin 1U
#define MX_SPI1_MOSI_GPIOx RTE_SPI1_MOSI_PORT
#define MX_SPI1_MOSI_GPIO_Pin RTE_SPI1_MOSI_BIT
#endif
#define MX_SPI1_SCK_Pin 1U
#define MX_SPI1_SCK_GPIOx RTE_SPI1_SCK_PORT
#define MX_SPI1_SCK_GPIO_Pin RTE_SPI1_SCK_BIT
#if (RTE_SPI1_NSS_PIN == 1)
#define MX_SPI1_NSS_Pin 1U
#define MX_SPI1_NSS_GPIOx RTE_SPI1_NSS_PORT
#define MX_SPI1_NSS_GPIO_Pin RTE_SPI1_NSS_BIT
#endif
#define MX_SPI1_REMAP_DEF AFIO_SPI1_NO_REMAP
#define MX_SPI1_REMAP RTE_SPI1_AF_REMAP
#endif
// SPI2 configuration definitions
#if (RTE_SPI2 == 1)
#if defined (STM32F10X_LD) || defined (STM32F10X_LD_VL)
#error "SPI2 not available for selected device!"
#endif
#define MX_SPI2
#if (RTE_SPI2_RX_DMA == 1)
#define MX_SPI2_RX_DMA_Instance DMAx_CHANNELy(RTE_SPI2_RX_DMA_NUMBER, RTE_SPI2_RX_DMA_CHANNEL)
#define MX_SPI2_RX_DMA_Number RTE_SPI2_RX_DMA_NUMBER
#define MX_SPI2_RX_DMA_Channel RTE_SPI2_RX_DMA_CHANNEL
#define MX_SPI2_RX_DMA_Priority RTE_SPI2_RX_DMA_PRIORITY
#define SPI2_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SPI2_RX_DMA_NUMBER, RTE_SPI2_RX_DMA_CHANNEL)
#endif
#if (RTE_SPI2_TX_DMA == 1)
#define MX_SPI2_TX_DMA_Instance DMAx_CHANNELy(RTE_SPI2_TX_DMA_NUMBER, RTE_SPI2_TX_DMA_CHANNEL)
#define MX_SPI2_TX_DMA_Number RTE_SPI2_TX_DMA_NUMBER
#define MX_SPI2_TX_DMA_Channel RTE_SPI2_TX_DMA_CHANNEL
#define MX_SPI2_TX_DMA_Priority RTE_SPI2_TX_DMA_PRIORITY
#define SPI2_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SPI2_TX_DMA_NUMBER, RTE_SPI2_TX_DMA_CHANNEL)
#endif
#if (RTE_SPI2_MISO == 1)
#define MX_SPI2_MISO_Pin 1U
#define MX_SPI2_MISO_GPIOx RTE_SPI2_MISO_PORT
#define MX_SPI2_MISO_GPIO_Pin RTE_SPI2_MISO_BIT
#endif
#if (RTE_SPI2_MOSI == 1)
#define MX_SPI2_MOSI_Pin 1U
#define MX_SPI2_MOSI_GPIOx RTE_SPI2_MOSI_PORT
#define MX_SPI2_MOSI_GPIO_Pin RTE_SPI2_MOSI_BIT
#endif
#define MX_SPI2_SCK_Pin 1U
#define MX_SPI2_SCK_GPIOx RTE_SPI2_SCK_PORT
#define MX_SPI2_SCK_GPIO_Pin RTE_SPI2_SCK_BIT
#if (RTE_SPI2_NSS_PIN == 1)
#define MX_SPI2_NSS_Pin 1U
#define MX_SPI2_NSS_GPIOx RTE_SPI2_NSS_PORT
#define MX_SPI2_NSS_GPIO_Pin RTE_SPI2_NSS_BIT
#endif
#define MX_SPI2_REMAP_DEF AFIO_UNAVAILABLE_REMAP
#define MX_SPI2_REMAP AFIO_UNAVAILABLE_REMAP
#endif
// SPI3 configuration definitions
#if (RTE_SPI3 == 1)
#if !defined(STM32F10X_HD) && !defined(STM32F10X_CL) && !defined(STM32F10X_XL) && !defined(STM32F10X_HD_VL)
#error "SPI3 is not available for selected device!"
#endif
#define MX_SPI3
#if (RTE_SPI3_RX_DMA == 1)
#define MX_SPI3_RX_DMA_Instance DMAx_CHANNELy(RTE_SPI3_RX_DMA_NUMBER, RTE_SPI3_RX_DMA_CHANNEL)
#define MX_SPI3_RX_DMA_Number RTE_SPI3_RX_DMA_NUMBER
#define MX_SPI3_RX_DMA_Channel RTE_SPI3_RX_DMA_CHANNEL
#define MX_SPI3_RX_DMA_Priority RTE_SPI3_RX_DMA_PRIORITY
#define SPI3_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SPI3_RX_DMA_NUMBER, RTE_SPI3_RX_DMA_CHANNEL)
#endif
#if (RTE_SPI3_TX_DMA == 1)
#define MX_SPI3_TX_DMA_Instance DMAx_CHANNELy(RTE_SPI3_TX_DMA_NUMBER, RTE_SPI3_TX_DMA_CHANNEL)
#define MX_SPI3_TX_DMA_Number RTE_SPI3_TX_DMA_NUMBER
#define MX_SPI3_TX_DMA_Channel RTE_SPI3_TX_DMA_CHANNEL
#define MX_SPI3_TX_DMA_Priority RTE_SPI3_TX_DMA_PRIORITY
#define SPI3_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_SPI3_TX_DMA_NUMBER, RTE_SPI3_TX_DMA_CHANNEL)
#endif
#if (RTE_SPI3_MISO == 1)
#define MX_SPI3_MISO_Pin 1U
#define MX_SPI3_MISO_GPIOx RTE_SPI3_MISO_PORT
#define MX_SPI3_MISO_GPIO_Pin RTE_SPI3_MISO_BIT
#endif
#if (RTE_SPI3_MOSI == 1)
#define MX_SPI3_MOSI_Pin 1U
#define MX_SPI3_MOSI_GPIOx RTE_SPI3_MOSI_PORT
#define MX_SPI3_MOSI_GPIO_Pin RTE_SPI3_MOSI_BIT
#endif
#define MX_SPI3_SCK_Pin 1U
#define MX_SPI3_SCK_GPIOx RTE_SPI3_SCK_PORT
#define MX_SPI3_SCK_GPIO_Pin RTE_SPI3_SCK_BIT
#if (RTE_SPI3_NSS_PIN == 1)
#define MX_SPI3_NSS_Pin 1U
#define MX_SPI3_NSS_GPIOx RTE_SPI3_NSS_PORT
#define MX_SPI3_NSS_GPIO_Pin RTE_SPI3_NSS_BIT
#endif
#if defined(STM32F10X_CL)
// SPI3 remap is available only in connectivity line devices
#define MX_SPI3_REMAP_DEF AFIO_SPI3_NO_REMAP
#define MX_SPI3_REMAP RTE_SPI3_AF_REMAP
#else
#if (RTE_SPI3_REMAP != 0)
#error "SPI3 remap is available only in connectivity line devices!"
#endif
#define MX_SPI3_REMAP_DEF AFIO_UNAVAILABLE_REMAP
#define MX_SPI3_REMAP AFIO_UNAVAILABLE_REMAP
#endif
#endif
#ifdef MX_SPI1
#if (defined(MX_SPI1_RX_DMA_Instance) || defined(MX_SPI1_TX_DMA_Instance))
#ifndef MX_SPI1_RX_DMA_Instance
#error "SPI1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_SPI1_TX_DMA_Instance
#error "SPI1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#ifdef MX_SPI2
#if (defined(MX_SPI2_RX_DMA_Instance) || defined(MX_SPI2_TX_DMA_Instance))
#ifndef MX_SPI2_RX_DMA_Instance
#error "SPI2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_SPI2_TX_DMA_Instance
#error "SPI2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#ifdef MX_SPI3
#if (defined(MX_SPI3_RX_DMA_Instance) || defined(MX_SPI3_TX_DMA_Instance))
#ifndef MX_SPI3_RX_DMA_Instance
#error "SPI3 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_SPI3_TX_DMA_Instance
#error "SPI3 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#if ((defined(MX_SPI1) && defined(MX_SPI1_RX_DMA_Instance)) || \
(defined(MX_SPI2) && defined(MX_SPI2_RX_DMA_Instance)) || \
(defined(MX_SPI3) && defined(MX_SPI3_RX_DMA_Instance)))
#define __SPI_DMA_RX
#endif
#if ((defined(MX_SPI1) && defined(MX_SPI1_TX_DMA_Instance)) || \
(defined(MX_SPI2) && defined(MX_SPI2_TX_DMA_Instance)) || \
(defined(MX_SPI3) && defined(MX_SPI3_TX_DMA_Instance)))
#define __SPI_DMA_TX
#endif
#if (defined(__SPI_DMA_RX) && defined(__SPI_DMA_TX))
#define __SPI_DMA
#endif
// Current driver status flag definition
#define SPI_INITIALIZED ((uint8_t)(1U)) // SPI initialized
#define SPI_POWERED ((uint8_t)(1U << 1)) // SPI powered on
#define SPI_CONFIGURED ((uint8_t)(1U << 2)) // SPI configured
#define SPI_DATA_LOST ((uint8_t)(1U << 3)) // SPI data lost occurred
#define SPI_MODE_FAULT ((uint8_t)(1U << 4)) // SPI mode fault occurred
// SPI DMA
typedef struct _SPI_DMA {
DMA_Channel_TypeDef *instance; // Channel registry interface
uint8_t dma_num; // DMA number
uint8_t ch_num; // Channel number
uint8_t priority; // Channel priority
} SPI_DMA;
// SPI pin
typedef const struct _SPI_PIN {
GPIO_TypeDef *port; // Port
uint32_t pin; // Pin
} SPI_PIN;
// SPI Input/Output Configuration
typedef const struct _SPI_IO {
SPI_PIN *mosi; // Pointer to MOSI pin configuration
SPI_PIN *miso; // Pointer to MISO pin configuration
SPI_PIN *nss; // Pointer to NSS pin configuration
SPI_PIN *sck; // Pointer to SCK pin configuration
AFIO_REMAP afio_def; // Default pin remapping setting
AFIO_REMAP afio; // Pin remapping information
} SPI_IO;
typedef struct _SPI_STATUS {
uint8_t busy; // Transmitter/Receiver busy flag
uint8_t data_lost; // Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
uint8_t mode_fault; // Mode fault detected; optional (cleared on start of transfer operation)
} SPI_STATUS;
// SPI Information (Run-time)
typedef struct _SPI_INFO {
ARM_SPI_SignalEvent_t cb_event; // Event Callback
SPI_STATUS status; // Status flags
uint8_t state; // Current SPI state
uint32_t mode; // Current SPI mode
} SPI_INFO;
// SPI Transfer Information (Run-Time)
typedef struct _SPI_TRANSFER_INFO {
uint32_t num; // Total number of transfers
uint8_t *rx_buf; // Pointer to in data buffer
uint8_t *tx_buf; // Pointer to out data buffer
uint32_t rx_cnt; // Number of data received
uint32_t tx_cnt; // Number of data sent
uint32_t dump_val; // Variable for dumping DMA data
uint16_t def_val; // Default transfer value
} SPI_TRANSFER_INFO;
// SPI Resources definition
typedef struct {
SPI_TypeDef *reg; // SPI peripheral pointer
uint32_t pclk; // Peripheral clock frequency
SPI_IO io; // SPI Input/Output pins
IRQn_Type irq_num; // SPI IRQ Number
SPI_DMA *rx_dma; // Receive stream register interface
SPI_DMA *tx_dma; // Transmit stream register interface
SPI_INFO *info; // Run-Time Information
SPI_TRANSFER_INFO *xfer; // SPI transfer information
} SPI_RESOURCES;
#endif /* __SPI_STM32F10X_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,480 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2016 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 29. March 2016
* $Revision: V2.2
*
* Project: USART Driver definitions for ST STM32F1xx
* -------------------------------------------------------------------------- */
#ifndef __USART_STM32F1XX_H
#define __USART_STM32F1XX_H
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "DMA_STM32F10x.h"
#include "Driver_USART.h"
#include "RTE_Components.h"
#include "RTE_Device.h"
#if ((defined(RTE_Drivers_USART1) || defined(RTE_Drivers_USART2) || \
defined(RTE_Drivers_USART3) || defined(RTE_Drivers_USART4) || \
defined(RTE_Drivers_USART5)) \
&& (RTE_USART1 == 0) \
&& (RTE_USART2 == 0) \
&& (RTE_USART3 == 0) \
&& (RTE_UART4 == 0) \
&& (RTE_UART5 == 0))
#error "USART not configured in RTE_Device.h!"
#endif
// USART1 configuration definitions
#if (RTE_USART1 == 1)
#define MX_USART1
#if (RTE_USART1_RX_DMA == 1)
#define MX_USART1_RX_DMA_Instance DMAx_CHANNELy(RTE_USART1_RX_DMA_NUMBER, RTE_USART1_RX_DMA_CHANNEL)
#define MX_USART1_RX_DMA_Number RTE_USART1_RX_DMA_NUMBER
#define MX_USART1_RX_DMA_Channel RTE_USART1_RX_DMA_CHANNEL
#define MX_USART1_RX_DMA_Priority RTE_USART1_RX_DMA_PRIORITY
#define USART1_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART1_RX_DMA_NUMBER, RTE_USART1_RX_DMA_CHANNEL)
#endif
#if (RTE_USART1_TX_DMA == 1)
#define MX_USART1_TX_DMA_Instance DMAx_CHANNELy(RTE_USART1_TX_DMA_NUMBER, RTE_USART1_TX_DMA_CHANNEL)
#define MX_USART1_TX_DMA_Number RTE_USART1_TX_DMA_NUMBER
#define MX_USART1_TX_DMA_Channel RTE_USART1_TX_DMA_CHANNEL
#define MX_USART1_TX_DMA_Priority RTE_USART1_TX_DMA_PRIORITY
#define USART1_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART1_TX_DMA_NUMBER, RTE_USART1_TX_DMA_CHANNEL)
#endif
#if (RTE_USART1_TX == 1)
#define MX_USART1_TX_Pin 1U
#define MX_USART1_TX_GPIOx RTE_USART1_TX_PORT
#define MX_USART1_TX_GPIO_Pin RTE_USART1_TX_BIT
#endif
#if (RTE_USART1_RX == 1)
#define MX_USART1_RX_Pin 1U
#define MX_USART1_RX_GPIOx RTE_USART1_RX_PORT
#define MX_USART1_RX_GPIO_Pin RTE_USART1_RX_BIT
#endif
#if (RTE_USART1_CK == 1)
#define MX_USART1_CK_Pin 1U
#define MX_USART1_CK_GPIOx RTE_USART1_CK_PORT
#define MX_USART1_CK_GPIO_Pin RTE_USART1_CK_BIT
#endif
#if (RTE_USART1_RTS == 1)
#define MX_USART1_RTS_Pin 1U
#define MX_USART1_RTS_GPIOx RTE_USART1_RTS_PORT
#define MX_USART1_RTS_GPIO_Pin RTE_USART1_RTS_BIT
#endif
#if (RTE_USART1_CTS == 1)
#define MX_USART1_CTS_Pin 1U
#define MX_USART1_CTS_GPIOx RTE_USART1_CTS_PORT
#define MX_USART1_CTS_GPIO_Pin RTE_USART1_CTS_BIT
#endif
#define MX_USART1_REMAP_DEF AFIO_USART1_NO_REMAP
#define MX_USART1_REMAP RTE_USART1_AF_REMAP
#endif
// USART2 configuration definitions
#if (RTE_USART2 == 1)
#define MX_USART2
#if (RTE_USART2_RX_DMA == 1)
#define MX_USART2_RX_DMA_Instance DMAx_CHANNELy(RTE_USART2_RX_DMA_NUMBER, RTE_USART2_RX_DMA_CHANNEL)
#define MX_USART2_RX_DMA_Number RTE_USART2_RX_DMA_NUMBER
#define MX_USART2_RX_DMA_Channel RTE_USART2_RX_DMA_CHANNEL
#define MX_USART2_RX_DMA_Priority RTE_USART2_RX_DMA_PRIORITY
#define USART2_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART2_RX_DMA_NUMBER, RTE_USART2_RX_DMA_CHANNEL)
#endif
#if (RTE_USART2_TX_DMA == 1)
#define MX_USART2_TX_DMA_Instance DMAx_CHANNELy(RTE_USART2_TX_DMA_NUMBER, RTE_USART2_TX_DMA_CHANNEL)
#define MX_USART2_TX_DMA_Number RTE_USART2_TX_DMA_NUMBER
#define MX_USART2_TX_DMA_Channel RTE_USART2_TX_DMA_CHANNEL
#define MX_USART2_TX_DMA_Priority RTE_USART2_TX_DMA_PRIORITY
#define USART2_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART2_TX_DMA_NUMBER, RTE_USART2_TX_DMA_CHANNEL)
#endif
#if (RTE_USART2_TX == 1)
#define MX_USART2_TX_Pin 1U
#define MX_USART2_TX_GPIOx RTE_USART2_TX_PORT
#define MX_USART2_TX_GPIO_Pin RTE_USART2_TX_BIT
#endif
#if (RTE_USART2_RX == 1)
#define MX_USART2_RX_Pin 1U
#define MX_USART2_RX_GPIOx RTE_USART2_RX_PORT
#define MX_USART2_RX_GPIO_Pin RTE_USART2_RX_BIT
#endif
#if (RTE_USART2_CK == 1)
#define MX_USART2_CK_Pin 1U
#define MX_USART2_CK_GPIOx RTE_USART2_CK_PORT
#define MX_USART2_CK_GPIO_Pin RTE_USART2_CK_BIT
#endif
#if (RTE_USART2_RTS == 1)
#define MX_USART2_RTS_Pin 1U
#define MX_USART2_RTS_GPIOx RTE_USART2_RTS_PORT
#define MX_USART2_RTS_GPIO_Pin RTE_USART2_RTS_BIT
#endif
#if (RTE_USART2_CTS == 1)
#define MX_USART2_CTS_Pin 1U
#define MX_USART2_CTS_GPIOx RTE_USART2_CTS_PORT
#define MX_USART2_CTS_GPIO_Pin RTE_USART2_CTS_BIT
#endif
#define MX_USART2_REMAP_DEF AFIO_USART2_NO_REMAP
#define MX_USART2_REMAP RTE_USART2_AF_REMAP
#endif
// USART3 configuration definitions
#if (RTE_USART3 == 1)
#if defined (STM32F10X_LD) || defined (STM32F10X_LD_VL)
#error "USART3 is not available for selected device!"
#endif
#define MX_USART3
#if (RTE_USART3_RX_DMA == 1)
#define MX_USART3_RX_DMA_Instance DMAx_CHANNELy(RTE_USART3_RX_DMA_NUMBER, RTE_USART3_RX_DMA_CHANNEL)
#define MX_USART3_RX_DMA_Number RTE_USART3_RX_DMA_NUMBER
#define MX_USART3_RX_DMA_Channel RTE_USART3_RX_DMA_CHANNEL
#define MX_USART3_RX_DMA_Priority RTE_USART3_RX_DMA_PRIORITY
#define USART3_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART3_RX_DMA_NUMBER, RTE_USART3_RX_DMA_CHANNEL)
#endif
#if (RTE_USART3_TX_DMA == 1)
#define MX_USART3_TX_DMA_Instance DMAx_CHANNELy(RTE_USART3_TX_DMA_NUMBER, RTE_USART3_TX_DMA_CHANNEL)
#define MX_USART3_TX_DMA_Number RTE_USART3_TX_DMA_NUMBER
#define MX_USART3_TX_DMA_Channel RTE_USART3_TX_DMA_CHANNEL
#define MX_USART3_TX_DMA_Priority RTE_USART3_TX_DMA_PRIORITY
#define USART3_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_USART3_TX_DMA_NUMBER, RTE_USART3_TX_DMA_CHANNEL)
#endif
#if (RTE_USART3_TX == 1)
#define MX_USART3_TX_Pin 1U
#define MX_USART3_TX_GPIOx RTE_USART3_TX_PORT
#define MX_USART3_TX_GPIO_Pin RTE_USART3_TX_BIT
#endif
#if (RTE_USART3_RX == 1)
#define MX_USART3_RX_Pin 1U
#define MX_USART3_RX_GPIOx RTE_USART3_RX_PORT
#define MX_USART3_RX_GPIO_Pin RTE_USART3_RX_BIT
#endif
#if (RTE_USART3_CK == 1)
#define MX_USART3_CK_Pin 1U
#define MX_USART3_CK_GPIOx RTE_USART3_CK_PORT
#define MX_USART3_CK_GPIO_Pin RTE_USART3_CK_BIT
#endif
#if (RTE_USART3_RTS == 1)
#define MX_USART3_RTS_Pin 1U
#define MX_USART3_RTS_GPIOx RTE_USART3_RTS_PORT
#define MX_USART3_RTS_GPIO_Pin RTE_USART3_RTS_BIT
#endif
#if (RTE_USART3_CTS == 1)
#define MX_USART3_CTS_Pin 1U
#define MX_USART3_CTS_GPIOx RTE_USART3_CTS_PORT
#define MX_USART3_CTS_GPIO_Pin RTE_USART3_CTS_BIT
#endif
#define MX_USART3_REMAP_DEF AFIO_USART3_NO_REMAP
#define MX_USART3_REMAP RTE_USART3_AF_REMAP
#endif
// UART4 configuration definitions
#if (RTE_UART4 == 1)
#if !defined(STM32F10X_HD) && !defined(STM32F10X_CL) && !defined(STM32F10X_XL) && !defined(STM32F10X_HD_VL)
#error "UART4 is not available for selected device!"
#endif
#define MX_UART4
#if (RTE_UART4_RX_DMA == 1)
#define MX_UART4_RX_DMA_Instance DMAx_CHANNELy(RTE_UART4_RX_DMA_NUMBER, RTE_UART4_RX_DMA_CHANNEL)
#define MX_UART4_RX_DMA_Number RTE_UART4_RX_DMA_NUMBER
#define MX_UART4_RX_DMA_Channel RTE_UART4_RX_DMA_CHANNEL
#define MX_UART4_RX_DMA_Priority RTE_UART4_RX_DMA_PRIORITY
#define UART4_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART4_RX_DMA_NUMBER, RTE_UART4_RX_DMA_CHANNEL)
#endif
#if (RTE_UART4_TX_DMA == 1)
#define MX_UART4_TX_DMA_Instance DMAx_CHANNELy(RTE_UART4_TX_DMA_NUMBER, RTE_UART4_TX_DMA_CHANNEL)
#define MX_UART4_TX_DMA_Number RTE_UART4_TX_DMA_NUMBER
#define MX_UART4_TX_DMA_Channel RTE_UART4_TX_DMA_CHANNEL
#define MX_UART4_TX_DMA_Priority RTE_UART4_TX_DMA_PRIORITY
#define UART4_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART4_TX_DMA_NUMBER, RTE_UART4_TX_DMA_CHANNEL)
#endif
#if (RTE_UART4_TX == 1)
#define MX_UART4_TX_Pin 1U
#define MX_UART4_TX_GPIOx RTE_UART4_TX_PORT
#define MX_UART4_TX_GPIO_Pin RTE_UART4_TX_BIT
#endif
#if (RTE_UART4_RX == 1)
#define MX_UART4_RX_Pin 1U
#define MX_UART4_RX_GPIOx RTE_UART4_RX_PORT
#define MX_UART4_RX_GPIO_Pin RTE_UART4_RX_BIT
#endif
#define MX_UART4_REMAP_DEF AFIO_UNAVAILABLE_REMAP
#define MX_UART4_REMAP AFIO_UNAVAILABLE_REMAP
#endif
// UART5 configuration definitions
#if (RTE_UART5 == 1)
#if !defined(STM32F10X_HD) && !defined(STM32F10X_CL) && !defined(STM32F10X_XL) && !defined(STM32F10X_HD_VL)
#error "UART5 is not available for selected device!"
#endif
#define MX_UART5
#if (RTE_UART5_RX_DMA == 1)
#define MX_UART5_RX_DMA_Instance DMAx_CHANNELy(RTE_UART5_RX_DMA_NUMBER, RTE_UART5_RX_DMA_CHANNEL)
#define MX_UART5_RX_DMA_Number RTE_UART5_RX_DMA_NUMBER
#define MX_UART5_RX_DMA_Channel RTE_UART5_RX_DMA_CHANNEL
#define MX_UART5_RX_DMA_Priority RTE_UART5_RX_DMA_PRIORITY
#define UART5_RX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART5_RX_DMA_NUMBER, RTE_UART5_RX_DMA_CHANNEL)
#endif
#if (RTE_UART5_TX_DMA == 1)
#define MX_UART5_TX_DMA_Instance DMAx_CHANNELy(RTE_UART5_TX_DMA_NUMBER, RTE_UART5_TX_DMA_CHANNEL)
#define MX_UART5_TX_DMA_Number RTE_UART5_TX_DMA_NUMBER
#define MX_UART5_TX_DMA_Channel RTE_UART5_TX_DMA_CHANNEL
#define MX_UART5_TX_DMA_Priority RTE_UART5_TX_DMA_PRIORITY
#define UART5_TX_DMA_Handler DMAx_CHANNELy_EVENT(RTE_UART5_TX_DMA_NUMBER, RTE_UART5_TX_DMA_CHANNEL)
#endif
#if (RTE_UART5_TX == 1)
#define MX_UART5_TX_Pin 1U
#define MX_UART5_TX_GPIOx RTE_UART5_TX_PORT
#define MX_UART5_TX_GPIO_Pin RTE_UART5_TX_BIT
#endif
#if (RTE_UART5_RX == 1)
#define MX_UART5_RX_Pin 1U
#define MX_UART5_RX_GPIOx RTE_UART5_RX_PORT
#define MX_UART5_RX_GPIO_Pin RTE_UART5_RX_BIT
#endif
#define MX_UART5_REMAP_DEF AFIO_UNAVAILABLE_REMAP
#define MX_UART5_REMAP AFIO_UNAVAILABLE_REMAP
#endif
#ifdef MX_USART1
#if (defined(MX_USART1_RX_DMA_Instance) || defined(MX_USART1_TX_DMA_Instance))
#ifndef MX_USART1_RX_DMA_Instance
#error "USART1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_USART1_TX_DMA_Instance
#error "USART1 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#ifdef MX_USART2
#if (defined(MX_USART2_RX_DMA_Instance) || defined(MX_USART2_TX_DMA_Instance))
#ifndef MX_USART2_RX_DMA_Instance
#error "USART2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_USART2_TX_DMA_Instance
#error "USART2 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#ifdef MX_USART3
#if (defined(MX_USART3_RX_DMA_Instance) || defined(MX_USART3_TX_DMA_Instance))
#ifndef MX_USART3_RX_DMA_Instance
#error "USART3 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_USART3_TX_DMA_Instance
#error "USART3 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#ifdef MX_UART4
#if (defined(MX_UART4_RX_DMA_Instance) || defined(MX_UART4_TX_DMA_Instance))
#ifndef MX_UART4_RX_DMA_Instance
#error "UART4 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_UART4_TX_DMA_Instance
#error "UART4 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#ifdef MX_UART5
#if (defined(MX_UART5_RX_DMA_Instance) || defined(MX_UART5_TX_DMA_Instance))
#ifndef MX_UART5_RX_DMA_Instance
#error "UART5 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#ifndef MX_UART5_TX_DMA_Instance
#error "UART5 using DMA requires Rx and Tx DMA channel enabled in RTE_Device.h or MX_Device.h!"
#endif
#endif
#endif
#if (defined(MX_USART1_RX_DMA_Instance) || \
defined(MX_USART2_RX_DMA_Instance) || \
defined(MX_USART3_RX_DMA_Instance) || \
defined(MX_UART4_RX_DMA_Instance ) || \
defined(MX_UART5_RX_DMA_Instance ))
#define __USART_DMA_RX
#endif
#if (defined(MX_USART1_TX_DMA_Instance) || \
defined(MX_USART2_TX_DMA_Instance) || \
defined(MX_USART3_TX_DMA_Instance) || \
defined(MX_UART4_TX_DMA_Instance ) || \
defined(MX_UART5_TX_DMA_Instance ))
#define __USART_DMA_TX
#endif
#if (defined(__USART_DMA_RX) && defined(__USART_DMA_TX))
#define __USART_DMA
#endif
// USART BRR macro
#define USART_DIVIDER(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_)))
#define USART_DIVIDER_MANTISA(_PCLK_, _BAUD_) (USART_DIVIDER((_PCLK_), (_BAUD_))/100)
#define USART_DIVIDER_FRACTION(_PCLK_, _BAUD_) (((USART_DIVIDER((_PCLK_), (_BAUD_)) - (USART_DIVIDER_MANTISA((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100)
#define USART_BAUDRATE_DIVIDER(_PCLK_, _BAUD_) ((USART_DIVIDER_MANTISA((_PCLK_), (_BAUD_)) << 4)|(USART_DIVIDER_FRACTION((_PCLK_), (_BAUD_)) & 0x0F))
// USART flags
#define USART_FLAG_INITIALIZED ((uint8_t)(1U))
#define USART_FLAG_POWERED ((uint8_t)(1U << 1))
#define USART_FLAG_CONFIGURED ((uint8_t)(1U << 2))
#define USART_FLAG_TX_ENABLED ((uint8_t)(1U << 3))
#define USART_FLAG_RX_ENABLED ((uint8_t)(1U << 4))
// USART synchronous xfer modes
#define USART_SYNC_MODE_TX ( 1UL )
#define USART_SYNC_MODE_RX ( 2UL )
#define USART_SYNC_MODE_TX_RX (USART_SYNC_MODE_TX | \
USART_SYNC_MODE_RX)
// USART DMA
typedef const struct _USART_DMA {
DMA_Channel_TypeDef *instance; // Channel registry interface
uint8_t dma_num; // DMA number
uint8_t ch_num; // Channel number
uint8_t priority; // Channel priority
} USART_DMA;
// USART pin
typedef const struct _USART_PIN {
GPIO_TypeDef *port; // Port
uint16_t pin; // Pin
} USART_PIN;
// USART Input/Output Configuration
typedef const struct _USART_IO {
USART_PIN *tx; // TX Pin identifier
USART_PIN *rx; // RX Pin identifier
USART_PIN *ck; // CLK Pin identifier
USART_PIN *rts; // RTS Pin identifier
USART_PIN *cts; // CTS Pin identifier
AFIO_REMAP afio_def; // Default pin remapping setting
AFIO_REMAP afio; // Pin remapping information
} USART_IO;
// USART Transfer Information (Run-Time)
typedef struct _USART_TRANSFER_INFO {
uint32_t rx_num; // Total number of receive data
uint32_t tx_num; // Total number of transmit data
uint8_t *rx_buf; // Pointer to in data buffer
uint8_t *tx_buf; // Pointer to out data buffer
uint32_t rx_cnt; // Number of data received
uint32_t tx_cnt; // Number of data sent
uint16_t dump_val; // Variable for dumping DMA data
uint16_t def_val; // Default transfer value
uint32_t sync_mode; // Synchronous mode flag
uint8_t break_flag; // Transmit break flag
uint8_t send_active; // Send active flag
} USART_TRANSFER_INFO;
typedef struct _USART_STATUS {
uint8_t tx_busy; // Transmitter busy flag
uint8_t rx_busy; // Receiver busy flag
uint8_t tx_underflow; // Transmit data underflow detected (cleared on start of next send operation)
uint8_t rx_overflow; // Receive data overflow detected (cleared on start of next receive operation)
uint8_t rx_break; // Break detected on receive (cleared on start of next receive operation)
uint8_t rx_framing_error; // Framing error detected on receive (cleared on start of next receive operation)
uint8_t rx_parity_error; // Parity error detected on receive (cleared on start of next receive operation)
} USART_STATUS;
// USART Information (Run-time)
typedef struct _USART_INFO {
ARM_USART_SignalEvent_t cb_event; // Event Callback
USART_STATUS status; // Status flags
uint8_t flags; // Current USART flags
uint32_t mode; // Current USART mode
uint32_t flow_control; // Flow control
} USART_INFO;
// USART Resources definition
typedef const struct {
ARM_USART_CAPABILITIES capabilities; // Capabilities
USART_TypeDef *reg; // USART peripheral pointer
uint32_t pclk; // Peripheral clock frequency
USART_IO io; // USART Input/Output pins
IRQn_Type irq_num; // USART IRQ Number
USART_DMA *dma_tx; // Transmit stream register interface
USART_DMA *dma_rx; // Receive stream register interface
USART_INFO *info; // Run-Time Information
USART_TRANSFER_INFO *xfer; // USART transfer information
} USART_RESOURCES;
#endif /* __USART_STM32F1XX_H */

View File

@ -0,0 +1,974 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2013-2017 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 19. September 2017
* $Revision: V2.1
*
* Driver: Driver_USBD0
* Configured: via RTE_Device.h configuration file
* Project: USB Full/Low-Speed Device Driver for ST STM32F10x
* ----------------------------------------------------------------------
* Use the following configuration settings in the middleware component
* to connect to this driver.
*
* Configuration Setting Value
* --------------------- -----
* Connect to hardware via Driver_USBD# = 0
* -------------------------------------------------------------------- */
/* History:
* Version 2.1
* Added support for CMSIS-RTOS2
* Version 2.0
* Updated to CMSIS Driver API V2.01
* Version 1.00
* Initial release
*/
#include <stdint.h>
#include <string.h>
#include "RTE_Components.h"
#if defined(RTE_CMSIS_RTOS2)
#include "cmsis_os2.h"
#elif defined(RTE_CMSIS_RTOS)
#include "cmsis_os.h"
#endif
#include "stm32f10x.h"
#include "GPIO_STM32F10x.h"
#include "USBD_STM32F10x.h"
#include "Driver_USBD.h"
#include "RTE_Device.h"
#include "RTE_Components.h"
// Do basic RTE configuration check
#if (RTE_USB_DEVICE == 0)
#error Enable USB Device in RTE_Device.h!
#endif
#ifndef USBD_MAX_ENDPOINT_NUM
#define USBD_MAX_ENDPOINT_NUM 8U
#endif
#if (USBD_MAX_ENDPOINT_NUM > 8)
#error Too many Endpoints, maximum IN/OUT Endpoint pairs that this driver supports is 8 !!!
#endif
// Endpoint buffer address
// Endpoint buffer sizes in bytes
// (total available memory for Endpoint buffers is 512 Bytes - EP_BUF_ADDR)
#ifndef USB_EP0_RX_BUF_SIZE
#define USB_EP0_RX_BUF_SIZE 8U
#endif
#define USB_EP0_RX_BUF_OFFSET 0x80U
#ifndef USB_EP0_TX_BUF_SIZE
#define USB_EP0_TX_BUF_SIZE 8U
#endif
#define USB_EP0_TX_BUF_OFFSET USB_EP0_RX_BUF_OFFSET + USB_EP0_RX_BUF_SIZE
#ifndef USB_EP1_RX_BUF_SIZE
#define USB_EP1_RX_BUF_SIZE 64U
#endif
#define USB_EP1_RX_BUF_OFFSET USB_EP0_TX_BUF_OFFSET + USB_EP0_TX_BUF_SIZE
#ifndef USB_EP1_TX_BUF_SIZE
#define USB_EP1_TX_BUF_SIZE 64U
#endif
#define USB_EP1_TX_BUF_OFFSET USB_EP1_RX_BUF_OFFSET + USB_EP1_RX_BUF_SIZE
#ifndef USB_EP2_RX_BUF_SIZE
#define USB_EP2_RX_BUF_SIZE 64U
#endif
#define USB_EP2_RX_BUF_OFFSET USB_EP1_TX_BUF_OFFSET + USB_EP1_TX_BUF_SIZE
#ifndef USB_EP2_TX_BUF_SIZE
#define USB_EP2_TX_BUF_SIZE 64U
#endif
#define USB_EP2_TX_BUF_OFFSET USB_EP2_RX_BUF_OFFSET + USB_EP2_RX_BUF_SIZE
#ifndef USB_EP3_RX_BUF_SIZE
#define USB_EP3_RX_BUF_SIZE 8U
#endif
#define USB_EP3_RX_BUF_OFFSET USB_EP2_TX_BUF_OFFSET + USB_EP2_TX_BUF_SIZE
#ifndef USB_EP3_TX_BUF_SIZE
#define USB_EP3_TX_BUF_SIZE 8U
#endif
#define USB_EP3_TX_BUF_OFFSET USB_EP3_RX_BUF_OFFSET + USB_EP3_RX_BUF_SIZE
#ifndef USB_EP4_RX_BUF_SIZE
#define USB_EP4_RX_BUF_SIZE 8U
#endif
#define USB_EP4_RX_BUF_OFFSET USB_EP3_TX_BUF_OFFSET + USB_EP3_TX_BUF_SIZE
#ifndef USB_EP4_TX_BUF_SIZE
#define USB_EP4_TX_BUF_SIZE 8U
#endif
#define USB_EP4_TX_BUF_OFFSET USB_EP4_RX_BUF_OFFSET + USB_EP4_RX_BUF_SIZE
#ifndef USB_EP5_RX_BUF_SIZE
#define USB_EP5_RX_BUF_SIZE 8U
#endif
#define USB_EP5_RX_BUF_OFFSET USB_EP4_TX_BUF_OFFSET + USB_EP4_TX_BUF_SIZE
#ifndef USB_EP5_TX_BUF_SIZE
#define USB_EP5_TX_BUF_SIZE 8U
#endif
#define USB_EP5_TX_BUF_OFFSET USB_EP5_RX_BUF_OFFSET + USB_EP5_RX_BUF_SIZE
#ifndef USB_EP6_RX_BUF_SIZE
#define USB_EP6_RX_BUF_SIZE 8U
#endif
#define USB_EP6_RX_BUF_OFFSET USB_EP5_TX_BUF_OFFSET + USB_EP5_TX_BUF_SIZE
#ifndef USB_EP6_TX_BUF_SIZE
#define USB_EP6_TX_BUF_SIZE 8U
#endif
#define USB_EP6_TX_BUF_OFFSET USB_EP6_RX_BUF_OFFSET + USB_EP6_RX_BUF_SIZE
#ifndef USB_EP7_RX_BUF_SIZE
#define USB_EP7_RX_BUF_SIZE 8U
#endif
#define USB_EP7_RX_BUF_OFFSET USB_EP6_TX_BUF_OFFSET + USB_EP6_TX_BUF_SIZE
#ifndef USB_EP7_TX_BUF_SIZE
#define USB_EP7_TX_BUF_SIZE 8U
#endif
#define USB_EP7_TX_BUF_OFFSET USB_EP7_RX_BUF_OFFSET + USB_EP7_RX_BUF_SIZE
#if ((USB_EP7_TX_BUF_OFFSET + USB_EP7_TX_BUF_SIZE) > 512U)
#error "The SUM of all Endpoint buffers sizes exceeds available dedicated RAM size (512 Bytes)."
#endif
// USBD Driver *****************************************************************
#define ARM_USBD_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,1)
// Driver Version
static const ARM_DRIVER_VERSION usbd_driver_version = { ARM_USBD_API_VERSION, ARM_USBD_DRV_VERSION };
// Driver Capabilities
static const ARM_USBD_CAPABILITIES usbd_driver_capabilities = {
0U, // VBUS Detection
0U, // Event VBUS On
0U // Event VBUS Off
};
#define EP_NUM(ep_addr) ((ep_addr) & ARM_USB_ENDPOINT_NUMBER_MASK)
#define EP_ID(ep_addr) ((EP_NUM(ep_addr) * 2U) + (((ep_addr) >> 7) & 1U))
typedef struct { // Endpoint structure definition
uint8_t *data;
uint32_t num;
uint32_t num_transferred_total;
uint16_t num_transferring;
uint16_t max_packet_size;
uint8_t active;
} ENDPOINT_t;
static ARM_USBD_SignalDeviceEvent_t SignalDeviceEvent;
static ARM_USBD_SignalEndpointEvent_t SignalEndpointEvent;
static bool hw_powered = false;
static bool hw_initialized = false;
static ARM_USBD_STATE usbd_state;
static uint8_t setup_packet[8]; // Setup packet data
static volatile uint8_t setup_received; // Setup packet received
// Endpoint buffer address
#define EP_BUF_ADDR (sizeof(EP_BUF_DSCR)*8)
// Pointer to Endpoint descriptor table
static EP_BUF_DSCR *pBUF_DSCR = (EP_BUF_DSCR *)USB_PMA_ADDR;
static const uint16_t EP_buff_offset[16] = { USB_EP0_RX_BUF_OFFSET, USB_EP0_TX_BUF_OFFSET,
USB_EP1_RX_BUF_OFFSET, USB_EP1_TX_BUF_OFFSET,
USB_EP2_RX_BUF_OFFSET, USB_EP2_TX_BUF_OFFSET,
USB_EP3_RX_BUF_OFFSET, USB_EP3_TX_BUF_OFFSET,
USB_EP4_RX_BUF_OFFSET, USB_EP4_TX_BUF_OFFSET,
USB_EP5_RX_BUF_OFFSET, USB_EP5_TX_BUF_OFFSET,
USB_EP6_RX_BUF_OFFSET, USB_EP6_TX_BUF_OFFSET,
USB_EP7_RX_BUF_OFFSET, USB_EP7_TX_BUF_OFFSET };
// Endpoints runtime information
static volatile ENDPOINT_t ep[(USBD_MAX_ENDPOINT_NUM + 1U) * 2U];
#define IN_EP_RESET(num) (EPxREG(EP_NUM(num)) = (EPxREG(EP_NUM(num)) & (EP_MASK | EP_STAT_TX | EP_DTOG_TX)) | EP_CTR_TX | EP_CTR_RX)
#define OUT_EP_RESET(num) (EPxREG(EP_NUM(num)) = (EPxREG(EP_NUM(num)) & (EP_MASK | EP_STAT_RX | EP_DTOG_RX)) | EP_CTR_TX | EP_CTR_RX)
// Auxiliary functions
/**
\fn static void IN_EP_Status (uint8_t ep_num, uint32_t stat)
\brief Called to update Endpoint status
*/
void IN_EP_Status (uint8_t ep_num, uint32_t stat) {
uint32_t num, val, ep_reg;
num = ep_num & ARM_USB_ENDPOINT_NUMBER_MASK;
stat &= EP_STAT_TX;
ep_reg = EPxREG(num);
val = (ep_reg & EP_STAT_TX) ^ stat;
val = (ep_reg & ~EP_STAT_TX) | val;
EPxREG(num) = (val & (EP_MASK | EP_STAT_TX)) | EP_CTR_TX | EP_CTR_RX;
}
/**
\fn static void OUT_EP_Status (uint8_t ep_num, uint32_t stat)
\brief Called to update Endpoint status
*/
void OUT_EP_Status (uint8_t ep_num, uint32_t stat) {
uint32_t num, val, ep_reg;
num = ep_num & ARM_USB_ENDPOINT_NUMBER_MASK;
stat &= EP_STAT_RX;
ep_reg = EPxREG(num);
val = (ep_reg & EP_STAT_RX) ^ stat;
val = (ep_reg & ~EP_STAT_RX) | val;
EPxREG(num) = (val & (EP_MASK | EP_STAT_RX)) | EP_CTR_TX | EP_CTR_RX;
}
/**
\fn void USBD_EP_HW_Read (uint8_t ep_addr)
\brief Read data from USB Endpoint.
\param[in] ep_addr Endpoint Address
- ep_addr.0..3: Address
- ep_addr.7: Direction
\return number of data bytes read
*/
static void USBD_EP_HW_Read (uint8_t ep_addr) {
volatile ENDPOINT_t *ptr_ep;
uint32_t cnt, i;
__packed uint8_t *ptr_dest_8;
__packed uint16_t *ptr_dest;
volatile uint32_t *ptr_src;
uint8_t ep_num;
uint8_t tmp_buf[4];
ptr_ep = &ep[EP_ID(ep_addr)];
ep_num = EP_NUM(ep_addr);
cnt = (pBUF_DSCR + ep_num)->COUNT_RX & EP_COUNT_MASK;
// Check for ZLP
if (cnt == 0U) { return; }
// Check if buffer available
if (ptr_ep->data == 0U) { return; }
// Copy data from FIFO
ptr_src = (uint32_t *)(USB_PMA_ADDR + 2*((pBUF_DSCR + ep_num)->ADDR_RX));
ptr_dest = (__packed uint16_t *)(ptr_ep->data + ptr_ep->num_transferred_total);
i = cnt / 2U;
while (i != 0U) {
*ptr_dest++ = *ptr_src++;
i--;
}
ptr_ep->num_transferred_total += cnt;
// If data size is not equal n*2
if ((cnt & 1U) != 0U) {
ptr_dest_8 = (uint8_t *)(ptr_dest);
*((__packed uint16_t *)tmp_buf) = *ptr_src;
*ptr_dest_8 = tmp_buf[0];
}
if (cnt != ptr_ep->max_packet_size) { ptr_ep->num = 0U; }
else { ptr_ep->num -= cnt; }
}
/**
\fn void USBD_EP_HW_Write (uint8_t ep_addr)
\brief Write data to Endpoint Buffer.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
*/
static void USBD_EP_HW_Write (uint8_t ep_addr) {
volatile ENDPOINT_t *ptr_ep;
uint8_t ep_num;
uint16_t num, i;
volatile uint32_t *ptr_dest;
__packed uint16_t *ptr_src;
ptr_ep = &ep[EP_ID(ep_addr)];
ep_num = EP_NUM(ep_addr);
if (ptr_ep->num > ptr_ep->max_packet_size) { num = ptr_ep->max_packet_size; }
else { num = ptr_ep->num; }
ptr_src = (__packed uint16_t *)(ptr_ep->data + ptr_ep->num_transferred_total);
ptr_dest = (uint32_t *)(USB_PMA_ADDR + 2*((pBUF_DSCR + ep_num)->ADDR_TX));
ptr_ep->num_transferring = num;
ptr_ep->num -= num;
// Copy data to EP Buffer
i = (num + 1U) >> 1;
while (i != 0U) {
*ptr_dest++ = *ptr_src++;
i--;
}
(pBUF_DSCR + ep_num)->COUNT_TX = num;
if ((EPxREG(ep_num) & EP_STAT_TX) != EP_TX_STALL) {
IN_EP_Status(ep_addr, EP_TX_VALID); // do not make EP valid if stalled
}
}
/**
\fn static void USBD_Reset (uint8_t ep_addr)
\brief Called after usbd reset interrupt to reset configuration
*/
static void USBD_Reset (void) {
ISTR = 0; // Clear Interrupt Status
CNTR = CNTR_CTRM | CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM | CNTR_ERRM | CNTR_PMAOVRM;
// Reset global variables
setup_received = 0U;
memset((void *)USB_PMA_ADDR, 0, EP_BUF_ADDR);
memset((void *)&usbd_state, 0, sizeof(usbd_state));
memset((void *)ep, 0, sizeof(ep));
BTABLE = 0x00; // set BTABLE Address
DADDR = DADDR_EF | 0; // Enable USB Default Address
}
// USBD Driver functions
/**
\fn ARM_DRIVER_VERSION USBD_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
*/
static ARM_DRIVER_VERSION USBD_GetVersion (void) { return usbd_driver_version; }
/**
\fn ARM_USBD_CAPABILITIES USBD_GetCapabilities (void)
\brief Get driver capabilities.
\return \ref ARM_USBD_CAPABILITIES
*/
static ARM_USBD_CAPABILITIES USBD_GetCapabilities (void) { return usbd_driver_capabilities; }
/**
\fn int32_t USBD_Initialize (ARM_USBD_SignalDeviceEvent_t cb_device_event,
ARM_USBD_SignalEndpointEvent_t cb_endpoint_event)
\brief Initialize USB Device Interface.
\param[in] cb_device_event Pointer to \ref ARM_USBD_SignalDeviceEvent
\param[in] cb_endpoint_event Pointer to \ref ARM_USBD_SignalEndpointEvent
\return \ref execution_status
*/
static int32_t USBD_Initialize (ARM_USBD_SignalDeviceEvent_t cb_device_event,
ARM_USBD_SignalEndpointEvent_t cb_endpoint_event) {
if (hw_initialized == true) {
return ARM_DRIVER_OK;
}
SignalDeviceEvent = cb_device_event;
SignalEndpointEvent = cb_endpoint_event;
#if (RTE_USB_DEVICE_CON_PIN)
// Configure CON pin (controls pull-up on D+ line)
GPIO_PortClock (RTE_USB_DEVICE_CON_PORT, true);
GPIO_PinWrite (RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, !RTE_USB_DEVICE_CON_ACTIVE);
if (!GPIO_PinConfigure(RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, GPIO_OUT_OPENDRAIN, GPIO_MODE_OUT10MHZ)) { return ARM_DRIVER_ERROR; }
#endif
hw_initialized = true;
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_Uninitialize (void)
\brief De-initialize USB Device Interface.
\return \ref execution_status
*/
static int32_t USBD_Uninitialize (void) {
#if (RTE_USB_DEVICE_CON_PIN)
// Unconfigure CON pin (controls pull-up on D+ line)
GPIO_PortClock (RTE_USB_DEVICE_CON_PORT, true);
GPIO_PinWrite (RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, !RTE_USB_DEVICE_CON_ACTIVE);
if (!GPIO_PinConfigure(RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, GPIO_IN_FLOATING, GPIO_MODE_INPUT)) { return ARM_DRIVER_ERROR; }
#endif
hw_initialized = false;
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_PowerControl (ARM_POWER_STATE state)
\brief Control USB Device Interface Power.
\param[in] state Power state
\return \ref execution_status
*/
static int32_t USBD_PowerControl (ARM_POWER_STATE state) {
switch (state) {
case ARM_POWER_OFF:
RCC->APB1ENR |= RCC_APB1ENR_USBEN; // Enable USB Device clock
NVIC_DisableIRQ (USB_LP_CAN1_RX0_IRQn); // Disable interrupt
NVIC_ClearPendingIRQ (USB_LP_CAN1_RX0_IRQn); // Clear pending interrupt
hw_powered = false; // Clear powered flag
CNTR = CNTR_FRES | CNTR_PDWN; // Switch off USB Device
#if (RTE_USB_DEVICE_CON_PIN)
if (!GPIO_PinConfigure(RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, GPIO_IN_FLOATING, GPIO_MODE_INPUT)) { return ARM_DRIVER_ERROR; }
#endif
RCC->APB1RSTR |= RCC_APB1RSTR_USBRST; // Reset USB Device
// Reset variables
setup_received = 0U;
memset((void *)&usbd_state, 0, sizeof(usbd_state));
memset((void *)ep, 0, sizeof(ep));
RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; // Disable USB Device clock
break;
case ARM_POWER_FULL:
if (hw_initialized == false) {
return ARM_DRIVER_ERROR;
}
if (hw_powered == true) {
return ARM_DRIVER_OK;
}
RCC->APB1ENR |= RCC_APB1ENR_USBEN; // Enable USB Device clock
RCC->APB1RSTR |= RCC_APB1RSTR_USBRST; // Reset USB Device
osDelay(1); // Wait 1 ms
RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST; // Reset USB Device
USBD_Reset (); // Reset variables and endpoint settings
hw_powered = true; // Set powered flag
NVIC_EnableIRQ (USB_LP_CAN1_RX0_IRQn); // Enable interrupt
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_DeviceConnect (void)
\brief Connect USB Device.
\return \ref execution_status
*/
static int32_t USBD_DeviceConnect (void) {
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
// Soft connect
#if (RTE_USB_DEVICE_CON_PIN)
GPIO_PinWrite (RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, RTE_USB_DEVICE_CON_ACTIVE);
#endif
CNTR = CNTR_FRES; // Force USB Reset
CNTR = 0;
ISTR = 0; // Clear Interrupt Status
CNTR = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; // USB Interrupt Mask
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_DeviceDisconnect (void)
\brief Disconnect USB Device.
\return \ref execution_status
*/
static int32_t USBD_DeviceDisconnect (void) {
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
CNTR = CNTR_FRES | CNTR_PDWN; // Switch Off USB Device
// Soft disconnect
#if (RTE_USB_DEVICE_CON_PIN)
GPIO_PinWrite (RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, !RTE_USB_DEVICE_CON_ACTIVE);
#endif
return ARM_DRIVER_OK;
}
/**
\fn ARM_USBD_STATE USBD_DeviceGetState (void)
\brief Get current USB Device State.
\return Device State \ref ARM_USBD_STATE
*/
static ARM_USBD_STATE USBD_DeviceGetState (void) {
return usbd_state;
}
/**
\fn int32_t USBD_DeviceRemoteWakeup (void)
\brief Trigger USB Remote Wakeup.
\return \ref execution_status
*/
static int32_t USBD_DeviceRemoteWakeup (void) {
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
CNTR |= CNTR; // Remote wakeup signaling
osDelay(2U);
CNTR &= ~CNTR;
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_DeviceSetAddress (uint8_t dev_addr)
\brief Set USB Device Address.
\param[in] dev_addr Device Address
\return \ref execution_status
*/
static int32_t USBD_DeviceSetAddress (uint8_t dev_addr) {
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
DADDR = DADDR_EF | dev_addr;
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_ReadSetupPacket (uint8_t *setup)
\brief Read setup packet received over Control Endpoint.
\param[out] setup Pointer to buffer for setup packet
\return \ref execution_status
*/
static int32_t USBD_ReadSetupPacket (uint8_t *setup) {
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
if (setup_received == 0U) { return ARM_DRIVER_ERROR; }
setup_received = 0U;
memcpy(setup, setup_packet, 8);
if (setup_received != 0U) { // If new setup packet was received while this was being read
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_EndpointConfigure (uint8_t ep_addr,
uint8_t ep_type,
uint16_t ep_max_packet_size)
\brief Configure USB Endpoint.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
\param[in] ep_type Endpoint Type (ARM_USB_ENDPOINT_xxx)
\param[in] ep_max_packet_size Endpoint Maximum Packet Size
\return \ref execution_status
*/
static int32_t USBD_EndpointConfigure (uint8_t ep_addr,
uint8_t ep_type,
uint16_t ep_max_packet_size) {
volatile ENDPOINT_t *ptr_ep;
uint8_t ep_num;
uint16_t ep_mps;
bool ep_dir;
uint32_t ep_reg;
ep_num = EP_NUM(ep_addr);
if (ep_num > USBD_MAX_ENDPOINT_NUM) { return ARM_DRIVER_ERROR; }
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
ptr_ep = &ep[EP_ID(ep_addr)];
if (ptr_ep->active != 0U) { return ARM_DRIVER_ERROR_BUSY; }
ep_mps = ep_max_packet_size & ARM_USB_ENDPOINT_MAX_PACKET_SIZE_MASK;
ep_dir = (ep_addr & ARM_USB_ENDPOINT_DIRECTION_MASK) == ARM_USB_ENDPOINT_DIRECTION_MASK;
// Check Endpoint buffer size configuration
if ((ep_mps + EP_buff_offset[EP_ID(ep_addr)]) > EP_buff_offset[EP_ID(ep_addr) + 1]) {
// Configured Endpoint buffer is too small
return ARM_DRIVER_ERROR;
}
// Clear Endpoint transfer and configuration information
memset((void *)(ptr_ep), 0, sizeof (ENDPOINT_t));
// Set maximum packet size to requested
ptr_ep->max_packet_size = ep_mps;
if (ep_dir != 0U) { // IN Endpoint
(pBUF_DSCR + ep_num)->ADDR_TX = EP_buff_offset[EP_ID(ep_addr)];
} else { // OUT Endpoint
(pBUF_DSCR + ep_num)->ADDR_RX = EP_buff_offset[EP_ID(ep_addr)];
if (ep_mps > 62) {
ep_mps = (ep_mps + 31) & ~31;
(pBUF_DSCR + ep_num)->COUNT_RX = ((ep_mps << 5) - 1) | 0x8000;
} else {
ep_mps = (ep_mps + 1) & ~1;
(pBUF_DSCR + ep_num)->COUNT_RX = ep_mps << 9;
}
}
switch (ep_type) {
case ARM_USB_ENDPOINT_CONTROL:
ep_reg = EP_CONTROL;
break;
case ARM_USB_ENDPOINT_ISOCHRONOUS:
ep_reg = EP_ISOCHRONOUS;
break;
case ARM_USB_ENDPOINT_BULK:
ep_reg = EP_BULK;
break;
case ARM_USB_ENDPOINT_INTERRUPT:
ep_reg = EP_INTERRUPT;
break;
}
if (ep_addr == 0U) {
// Enable Endpoint 0 to receive Setup and OUT packets
EPxREG(0) = EP_CONTROL | EP_RX_VALID;
} else if (ep_addr != 0x80U){
ep_reg |= ep_num;
EPxREG(ep_num) = ep_reg;
if (ep_dir != 0U) { // IN Endpoint
IN_EP_RESET(ep_num);
IN_EP_Status(ep_num, EP_TX_NAK);
} else { // OUT Endpoint
OUT_EP_RESET(ep_num);
OUT_EP_Status(ep_num, EP_RX_NAK);
}
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_EndpointUnconfigure (uint8_t ep_addr)
\brief Unconfigure USB Endpoint.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
\return \ref execution_status
*/
static int32_t USBD_EndpointUnconfigure (uint8_t ep_addr) {
volatile ENDPOINT_t *ptr_ep;
uint8_t ep_num;
bool ep_dir;
ep_num = EP_NUM(ep_addr);
if (ep_num > USBD_MAX_ENDPOINT_NUM) { return ARM_DRIVER_ERROR; }
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
ptr_ep = &ep[EP_ID(ep_addr)];
if (ptr_ep->active != 0U) { return ARM_DRIVER_ERROR_BUSY; }
ep_dir = (ep_addr & ARM_USB_ENDPOINT_DIRECTION_MASK) == ARM_USB_ENDPOINT_DIRECTION_MASK;
if (ep_dir != 0U) { // IN Endpoint
IN_EP_RESET(ep_num);
IN_EP_Status(ep_num, EP_TX_DIS);
} else { // OUT Endpoint
OUT_EP_RESET(ep_num);
OUT_EP_Status(ep_num, EP_RX_DIS);
}
// Clear Endpoint transfer and configuration information
memset((void *)(ptr_ep), 0, sizeof (ENDPOINT_t));
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_EndpointStall (uint8_t ep_addr, bool stall)
\brief Set/Clear Stall for USB Endpoint.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
\param[in] stall Operation
- \b false Clear
- \b true Set
\return \ref execution_status
*/
static int32_t USBD_EndpointStall (uint8_t ep_addr, bool stall) {
volatile ENDPOINT_t *ptr_ep;
uint8_t ep_num;
bool ep_dir;
ep_num = EP_NUM(ep_addr);
if (ep_num > USBD_MAX_ENDPOINT_NUM) { return ARM_DRIVER_ERROR; }
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
ptr_ep = &ep[EP_ID(ep_addr)];
if (ptr_ep->active != 0U) { return ARM_DRIVER_ERROR_BUSY; }
ep_dir = (ep_addr & ARM_USB_ENDPOINT_DIRECTION_MASK) == ARM_USB_ENDPOINT_DIRECTION_MASK;
if (stall == true) {
if (ep_dir != 0U) { // IN Endpoint
IN_EP_Status(ep_num, EP_TX_STALL); // Stall IN Endpoint
} else { // OUT Endpoint
OUT_EP_Status(ep_num, EP_RX_STALL); // Stall OUT Endpoint
}
} else {
if (ep_dir != 0U) { // IN Endpoint
IN_EP_RESET(ep_num); // Reset DTog Bits
IN_EP_Status(ep_num, EP_TX_NAK); // Clear STALL
} else { // OUT Endpoint
OUT_EP_RESET(ep_num); // Reset DTog Bits
OUT_EP_Status(ep_num, EP_RX_NAK); // Clear Stall
}
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t USBD_EndpointTransfer (uint8_t ep_addr, uint8_t *data, uint32_t num)
\brief Read data from or Write data to USB Endpoint.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
\param[out] data Pointer to buffer for data to read or with data to write
\param[in] num Number of data bytes to transfer
\return \ref execution_status
*/
static int32_t USBD_EndpointTransfer (uint8_t ep_addr, uint8_t *data, uint32_t num) {
volatile ENDPOINT_t *ptr_ep;
uint8_t ep_num;
bool ep_dir;
ep_num = EP_NUM(ep_addr);
if (ep_num > USBD_MAX_ENDPOINT_NUM) { return ARM_DRIVER_ERROR; }
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
ptr_ep = &ep[EP_ID(ep_addr)];
if (ptr_ep->active != 0U) { return ARM_DRIVER_ERROR_BUSY; }
ep_dir = (ep_addr & ARM_USB_ENDPOINT_DIRECTION_MASK) == ARM_USB_ENDPOINT_DIRECTION_MASK;
ptr_ep->active = 1U;
ptr_ep->data = data;
ptr_ep->num = num;
ptr_ep->num_transferred_total = 0U;
ptr_ep->num_transferring = 0U;
if (ep_dir != 0U) { // IN Endpoint
USBD_EP_HW_Write (ep_addr); // Write data to Endpoint buffer
} else { // OUT Endpoint
OUT_EP_Status(ep_num, EP_RX_VALID); // OUT EP able to receive data
}
return ARM_DRIVER_OK;
}
/**
\fn uint32_t USBD_EndpointTransferGetResult (uint8_t ep_addr)
\brief Get result of USB Endpoint transfer.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
\return number of successfully transferred data bytes
*/
static uint32_t USBD_EndpointTransferGetResult (uint8_t ep_addr) {
if (EP_NUM(ep_addr) > USBD_MAX_ENDPOINT_NUM) { return 0U; }
return (ep[EP_ID(ep_addr)].num_transferred_total);
}
/**
\fn int32_t USBD_EndpointTransferAbort (uint8_t ep_addr)
\brief Abort current USB Endpoint transfer.
\param[in] ep_addr Endpoint Address
- ep_addr.0..7: Address
- ep_addr.7: Direction
\return \ref execution_status
*/
static int32_t USBD_EndpointTransferAbort (uint8_t ep_addr) {
volatile ENDPOINT_t *ptr_ep;
uint8_t ep_num;
bool ep_dir;
ep_num = EP_NUM(ep_addr);
if (ep_num > USBD_MAX_ENDPOINT_NUM) { return ARM_DRIVER_ERROR; }
if (hw_powered == false) { return ARM_DRIVER_ERROR; }
ep_dir = (ep_addr & ARM_USB_ENDPOINT_DIRECTION_MASK) == ARM_USB_ENDPOINT_DIRECTION_MASK;
ptr_ep = &ep[EP_ID(ep_addr)];
ptr_ep->num = 0U;
if (ep_dir != 0U) { // IN Endpoint
IN_EP_Status(ep_num, EP_TX_NAK); // Set NAK
} else { // OUT Endpoint
OUT_EP_Status(ep_num, EP_RX_NAK); // Set NAK
}
ptr_ep->active = 0U;
return ARM_DRIVER_OK;
}
/**
\fn uint16_t USBD_GetFrameNumber (void)
\brief Get current USB Frame Number.
\return Frame Number
*/
static uint16_t USBD_GetFrameNumber (void) {
if (hw_powered == false) { return 0U; }
return (FNR & FNR_FN);
}
/**
\fn void USB_LP_CAN1_RX0_IRQHandler (void)
\brief USB Device Interrupt Routine (IRQ).
*/
void USB_LP_CAN1_RX0_IRQHandler (void) {
__packed uint16_t *ptr_dest;
volatile uint32_t *ptr_src;
volatile ENDPOINT_t *ptr_ep;
uint32_t istr, ep_num, val, i;
istr = ISTR;
// Reset interrupt
if (istr & ISTR_RESET) {
USBD_Reset();
SignalDeviceEvent(ARM_USBD_EVENT_RESET);
ISTR = ~ISTR_RESET;
}
// Suspend interrupt
if (istr & ISTR_SUSP) {
CNTR |= CNTR_SUSPM;
usbd_state.active = 0U;
SignalDeviceEvent(ARM_USBD_EVENT_SUSPEND);
ISTR = ~ISTR_SUSP;
}
// Resume interrupt
if (istr & ISTR_WKUP) {
usbd_state.active = 1U;
CNTR &= ~CNTR_SUSPM;
SignalDeviceEvent(ARM_USBD_EVENT_RESUME);
ISTR = ~ISTR_WKUP;
}
// PMA Over/underrun
if (istr & ISTR_PMAOVR) {
ISTR = ~ISTR_PMAOVR;
}
// Error: No Answer, CRC Error, Bit Stuff Error, Frame Format Error
if (istr & ISTR_ERR) {
ISTR = ~ISTR_ERR;
}
// Endpoint interrupts
if ((istr = ISTR) & ISTR_CTR) {
// ISTR = ~ISTR_CTR;
ep_num = istr & ISTR_EP_ID;
val = EPxREG(ep_num);
if (val & EP_CTR_RX) {
ptr_ep = &ep[EP_ID(ep_num)];
EPxREG(ep_num) = val & ~EP_CTR_RX & EP_MASK;
// Setup Packet
if (val & EP_SETUP) {
// Read Setup Packet
ptr_src = (uint32_t *)(USB_PMA_ADDR + 2*((pBUF_DSCR)->ADDR_RX));
ptr_dest = (__packed uint16_t *)(setup_packet);
for (i = 0U; i < 4U; i++) {
*ptr_dest++ = *ptr_src++;
}
setup_received = 1U;
SignalEndpointEvent(ep_num, ARM_USBD_EVENT_SETUP);
} else {
// OUT Packet
USBD_EP_HW_Read(ep_num);
if (ptr_ep->num != 0U) {
OUT_EP_Status(ep_num, EP_RX_VALID);
} else {
ptr_ep->active = 0U;
SignalEndpointEvent(ep_num, ARM_USBD_EVENT_OUT);
}
}
}
// IN Packet
if (val & EP_CTR_TX) {
ptr_ep = &ep[EP_ID(ep_num | ARM_USB_ENDPOINT_DIRECTION_MASK)];
EPxREG(ep_num) = val & ~EP_CTR_TX & EP_MASK;
ptr_ep->num_transferred_total += ptr_ep->num_transferring;
if (ptr_ep->num == 0U) {
ptr_ep->data = NULL;
ptr_ep->active = 0U;
SignalEndpointEvent(ep_num | ARM_USB_ENDPOINT_DIRECTION_MASK, ARM_USBD_EVENT_IN);
} else {
USBD_EP_HW_Write(ep_num | ARM_USB_ENDPOINT_DIRECTION_MASK);
}
}
}
}
ARM_DRIVER_USBD Driver_USBD0 = {
USBD_GetVersion,
USBD_GetCapabilities,
USBD_Initialize,
USBD_Uninitialize,
USBD_PowerControl,
USBD_DeviceConnect,
USBD_DeviceDisconnect,
USBD_DeviceGetState,
USBD_DeviceRemoteWakeup,
USBD_DeviceSetAddress,
USBD_ReadSetupPacket,
USBD_EndpointConfigure,
USBD_EndpointUnconfigure,
USBD_EndpointStall,
USBD_EndpointTransfer,
USBD_EndpointTransferGetResult,
USBD_EndpointTransferAbort,
USBD_GetFrameNumber
};

View File

@ -0,0 +1,119 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2013 ARM Limited. All rights reserved.
*
* $Date: 12. September 2013
* $Revision: V1.00
*
* Project: USB Full/Low-Speed Driver Header for ST STM32F10x
* -------------------------------------------------------------------- */
#ifndef __USBREG_H
#define __USBREG_H
#define REG(x) (*((volatile unsigned int *)(x)))
#define USB_BASE_ADDR 0x40005C00 /* USB Registers Base Address */
#define USB_PMA_ADDR 0x40006000 /* USB Packet Memory Area Address */
/* Common Registers */
#define CNTR REG(USB_BASE_ADDR + 0x40) /* Control Register */
#define ISTR REG(USB_BASE_ADDR + 0x44) /* Interrupt Status Register */
#define FNR REG(USB_BASE_ADDR + 0x48) /* Frame Number Register */
#define DADDR REG(USB_BASE_ADDR + 0x4C) /* Device Address Register */
#define BTABLE REG(USB_BASE_ADDR + 0x50) /* Buffer Table Address Register */
/* CNTR: Control Register Bit Definitions */
#define CNTR_CTRM 0x8000 /* Correct Transfer Interrupt Mask */
#define CNTR_PMAOVRM 0x4000 /* Packet Memory Aerea Over/underrun Interrupt Mask */
#define CNTR_ERRM 0x2000 /* Error Interrupt Mask */
#define CNTR_WKUPM 0x1000 /* Wake-up Interrupt Mask */
#define CNTR_SUSPM 0x0800 /* Suspend Mode Interrupt Mask */
#define CNTR_RESETM 0x0400 /* USB Reset Interrupt Mask */
#define CNTR_SOFM 0x0200 /* Start of Frame Interrupt Mask */
#define CNTR_ESOFM 0x0100 /* Expected Start of Frame Interrupt Mask */
#define CNTR_RESUME 0x0010 /* Resume Request */
#define CNTR_FSUSP 0x0008 /* Force Suspend */
#define CNTR_LPMODE 0x0004 /* Low-power Mode */
#define CNTR_PDWN 0x0002 /* Power Down */
#define CNTR_FRES 0x0001 /* Force USB Reset */
/* ISTR: Interrupt Status Register Bit Definitions */
#define ISTR_CTR 0x8000 /* Correct Transfer */
#define ISTR_PMAOVR 0x4000 /* Packet Memory Aerea Over/underrun */
#define ISTR_ERR 0x2000 /* Error */
#define ISTR_WKUP 0x1000 /* Wake-up */
#define ISTR_SUSP 0x0800 /* Suspend Mode */
#define ISTR_RESET 0x0400 /* USB Reset */
#define ISTR_SOF 0x0200 /* Start of Frame */
#define ISTR_ESOF 0x0100 /* Expected Start of Frame */
#define ISTR_DIR 0x0010 /* Direction of Transaction */
#define ISTR_EP_ID 0x000F /* EndPoint Identifier */
/* FNR: Frame Number Register Bit Definitions */
#define FNR_RXDP 0x8000 /* D+ Data Line Status */
#define FNR_RXDM 0x4000 /* D- Data Line Status */
#define FNR_LCK 0x2000 /* Locked */
#define FNR_LSOF 0x1800 /* Lost SOF */
#define FNR_FN 0x07FF /* Frame Number */
/* DADDR: Device Address Register Bit Definitions */
#define DADDR_EF 0x0080 /* Enable Function */
#define DADDR_ADD 0x007F /* Device Address */
/* EndPoint Registers */
#define EPxREG(x) REG(USB_BASE_ADDR + 4*(x))
/* EPxREG: EndPoint Registers Bit Definitions */
#define EP_CTR_RX 0x8000 /* Correct RX Transfer */
#define EP_DTOG_RX 0x4000 /* RX Data Toggle */
#define EP_STAT_RX 0x3000 /* RX Status */
#define EP_SETUP 0x0800 /* EndPoint Setup */
#define EP_TYPE 0x0600 /* EndPoint Type */
#define EP_KIND 0x0100 /* EndPoint Kind */
#define EP_CTR_TX 0x0080 /* Correct TX Transfer */
#define EP_DTOG_TX 0x0040 /* TX Data Toggle */
#define EP_STAT_TX 0x0030 /* TX Status */
#define EP_EA 0x000F /* EndPoint Address */
/* EndPoint Register Mask (No Toggle Fields) */
#define EP_MASK (EP_CTR_RX|EP_SETUP|EP_TYPE|EP_KIND|EP_CTR_TX|EP_EA)
/* EP_TYPE: EndPoint Types */
#define EP_BULK 0x0000 /* BULK EndPoint */
#define EP_CONTROL 0x0200 /* CONTROL EndPoint */
#define EP_ISOCHRONOUS 0x0400 /* ISOCHRONOUS EndPoint */
#define EP_INTERRUPT 0x0600 /* INTERRUPT EndPoint */
/* EP_KIND: EndPoint Kind */
#define EP_DBL_BUF EP_KIND /* Double Buffer for Bulk Endpoint */
#define EP_STATUS_OUT EP_KIND /* Status Out for Control Endpoint */
/* EP_STAT_TX: TX Status */
#define EP_TX_DIS 0x0000 /* Disabled */
#define EP_TX_STALL 0x0010 /* Stalled */
#define EP_TX_NAK 0x0020 /* NAKed */
#define EP_TX_VALID 0x0030 /* Valid */
/* EP_STAT_RX: RX Status */
#define EP_RX_DIS 0x0000 /* Disabled */
#define EP_RX_STALL 0x1000 /* Stalled */
#define EP_RX_NAK 0x2000 /* NAKed */
#define EP_RX_VALID 0x3000 /* Valid */
/* Endpoint Buffer Descriptor */
typedef struct _EP_BUF_DSCR {
unsigned int ADDR_TX;
unsigned int COUNT_TX;
unsigned int ADDR_RX;
unsigned int COUNT_RX;
} EP_BUF_DSCR;
#define EP_ADDR_MASK 0xFFFE /* Address Mask */
#define EP_COUNT_MASK 0x03FF /* Count Mask */
#endif /* __USBREG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff