添加一些关于midi播放的项目
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief providing generic malloc() and free() engine.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#ifndef __CC_ARM
|
||||
#pragma section = "HEAP"
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* This struct forms the minimum block size which is allocated, and
|
||||
* also forms the linked list for the memory space used with alloc()
|
||||
* and free(). It is padded so that on a 32-bit machine, all malloc'ed
|
||||
* pointers are 16-byte aligned.
|
||||
*/
|
||||
typedef struct ALLOC_HDR
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct ALLOC_HDR *ptr;
|
||||
unsigned int size;
|
||||
} s;
|
||||
unsigned int align;
|
||||
unsigned int pad;
|
||||
} ALLOC_HDR;
|
||||
|
||||
static ALLOC_HDR base;
|
||||
static ALLOC_HDR *freep = NULL;
|
||||
|
||||
/********************************************************************/
|
||||
void
|
||||
free (void *ap)
|
||||
{
|
||||
ALLOC_HDR *bp, *p;
|
||||
|
||||
bp = (ALLOC_HDR *)ap - 1; /* point to block header */
|
||||
for (p = freep; !((bp > p) && (bp < p->s.ptr)) ; p = p->s.ptr)
|
||||
{
|
||||
if ((p >= p->s.ptr) && ((bp > p) || (bp < p->s.ptr)))
|
||||
{
|
||||
break; /* freed block at start or end of arena */
|
||||
}
|
||||
}
|
||||
|
||||
if ((bp + bp->s.size) == p->s.ptr)
|
||||
{
|
||||
bp->s.size += p->s.ptr->s.size;
|
||||
bp->s.ptr = p->s.ptr->s.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
bp->s.ptr = p->s.ptr;
|
||||
}
|
||||
|
||||
if ((p + p->s.size) == bp)
|
||||
{
|
||||
p->s.size += bp->s.size;
|
||||
p->s.ptr = bp->s.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->s.ptr = bp;
|
||||
}
|
||||
|
||||
freep = p;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
void *
|
||||
malloc (unsigned nbytes)
|
||||
{
|
||||
/* Get addresses for the HEAP start and end */
|
||||
#if defined(CW)
|
||||
extern char __HEAP_START[];
|
||||
extern char __HEAP_END[];
|
||||
#elif defined(IAR)
|
||||
char* __HEAP_START = __section_begin("HEAP");
|
||||
char* __HEAP_END = __section_end("HEAP");
|
||||
#elif defined(KEIL)
|
||||
extern uint32_t HEAP$$Base;
|
||||
extern uint32_t HEAP$$Limit;
|
||||
uint32_t __HEAP_START = (uint32_t)&HEAP$$Base;
|
||||
uint32_t __HEAP_END = (uint32_t)&HEAP$$Limit;
|
||||
#endif
|
||||
|
||||
ALLOC_HDR *p, *prevp;
|
||||
unsigned nunits;
|
||||
|
||||
nunits = ((nbytes+sizeof(ALLOC_HDR)-1) / sizeof(ALLOC_HDR)) + 1;
|
||||
|
||||
if ((prevp = freep) == NULL)
|
||||
{
|
||||
p = (ALLOC_HDR *)__HEAP_START;
|
||||
p->s.size = ( ((uint32)__HEAP_END - (uint32)__HEAP_START)
|
||||
/ sizeof(ALLOC_HDR) );
|
||||
p->s.ptr = &base;
|
||||
base.s.ptr = p;
|
||||
base.s.size = 0;
|
||||
prevp = freep = &base;
|
||||
}
|
||||
|
||||
for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr)
|
||||
{
|
||||
if (p->s.size >= nunits)
|
||||
{
|
||||
if (p->s.size == nunits)
|
||||
{
|
||||
prevp->s.ptr = p->s.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->s.size -= nunits;
|
||||
p += p->s.size;
|
||||
p->s.size = nunits;
|
||||
}
|
||||
freep = prevp;
|
||||
return (void *)(p + 1);
|
||||
}
|
||||
|
||||
if (p == freep)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,28 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide macro for software assertions.
|
||||
*
|
||||
* ASSERT macro defined in assert.h calls assert_failed().
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
const char ASSERT_FAILED_STR[] = "Assertion failed in %s at line %d\n";
|
||||
|
||||
/********************************************************************/
|
||||
void
|
||||
assert_failed(char *file, int line)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(ASSERT_FAILED_STR, file, line);
|
||||
|
||||
while (1)
|
||||
{
|
||||
// platform_led_display(0xFF);
|
||||
for (i = 100000; i; i--) ;
|
||||
// platform_led_display(0x00);
|
||||
for (i = 100000; i; i--) ;
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,25 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide macro for software assertions.
|
||||
*
|
||||
* assert_failed() defined in assert.c.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _ASSERT_H_
|
||||
#define _ASSERT_H_
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
void assert_failed(char *, int);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define ASSERT(expr) \
|
||||
if (!(expr)) \
|
||||
assert_failed(__FILE__, __LINE__)
|
||||
#else
|
||||
#define ASSERT(expr)
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
#endif /* _ASSERT_H_ */
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide header files to be included by all project files.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#define swap_bytes(ptrWord) *ptrWord = (*ptrWord >>8) | (*ptrWord<<8)
|
||||
typedef unsigned long dword;
|
||||
typedef unsigned short word;
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Debug prints ON (#define) or OFF (#undef)
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
#define DEBUG_PRINT
|
||||
|
||||
/*
|
||||
* Include the generic CPU header file
|
||||
*/
|
||||
#include "arm_cm0.h"
|
||||
|
||||
/*
|
||||
* Include the platform specific header file
|
||||
*/
|
||||
#if (defined(NV32))
|
||||
#include "NV32_config.h"
|
||||
#elif (defined(FRDM_NV32M3))
|
||||
#include "NV32M3_config.h"
|
||||
#elif (defined(FRDM_NV32M4))
|
||||
#include "NV32M4_config.h"
|
||||
#else
|
||||
#error "No valid board defined"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include the cpu specific header file
|
||||
*/
|
||||
#if (defined(CPU_NV32))
|
||||
#include "NV32.h"
|
||||
#elif (defined(CPU_NV32M3))
|
||||
#include "NV32M3.h"
|
||||
#elif (defined(CPU_NV32M4))
|
||||
#include "NV32M4.h"
|
||||
#else
|
||||
#error "No valid CPU defined"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Include any toolchain specfic header files
|
||||
*/
|
||||
#if (defined(__MWERKS__))
|
||||
#include "mwerks.h"
|
||||
#elif (defined(__DCC__))
|
||||
#include "build/wrs/diab.h"
|
||||
#elif (defined(__ghs__))
|
||||
#include "build/ghs/ghs.h"
|
||||
#elif (defined(__GNUC__))
|
||||
#if (defined(IAR))
|
||||
#include "build/gnu/gnu.h"
|
||||
#endif
|
||||
#elif (defined(IAR))
|
||||
#include "iar.h"
|
||||
#elif (defined(KEIL))
|
||||
|
||||
#else
|
||||
#warning "No toolchain specific header included"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include common utilities
|
||||
*/
|
||||
#include "assert.h"
|
||||
#include "io.h"
|
||||
#include "startup.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#if (defined(IAR))
|
||||
#include "intrinsics.h"
|
||||
#endif
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* _COMMON_H_ */
|
||||
@@ -0,0 +1,822 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cm0plus.h
|
||||
* @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File
|
||||
* @version V4.00
|
||||
* @date 22. August 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CM0PLUS_H_GENERIC
|
||||
#define __CORE_CM0PLUS_H_GENERIC
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
|
||||
CMSIS violates the following MISRA-C:2004 rules:
|
||||
|
||||
\li Required Rule 8.5, object/function definition in header file.<br>
|
||||
Function definitions in header files are used to allow 'inlining'.
|
||||
|
||||
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
|
||||
Unions are used for effective representation of core registers.
|
||||
|
||||
\li Advisory Rule 19.7, Function-like macro defined.<br>
|
||||
Function-like macros are used to allow more efficient code.
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* CMSIS definitions
|
||||
******************************************************************************/
|
||||
/** \ingroup Cortex-M0+
|
||||
@{
|
||||
*/
|
||||
|
||||
/* CMSIS CM0P definitions */
|
||||
#define __CM0PLUS_CMSIS_VERSION_MAIN (0x04) /*!< [31:16] CMSIS HAL main version */
|
||||
#define __CM0PLUS_CMSIS_VERSION_SUB (0x00) /*!< [15:0] CMSIS HAL sub version */
|
||||
#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16) | \
|
||||
__CM0PLUS_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */
|
||||
|
||||
#define __CORTEX_M (0x00) /*!< Cortex-M Core */
|
||||
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#define __ASM __asm /*!< asm keyword for ARM Compiler */
|
||||
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
|
||||
#define __STATIC_INLINE static __inline
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#define __ASM __asm /*!< asm keyword for GNU Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for GNU Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
#define __ASM __asm /*!< asm keyword for IAR Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __TMS470__ )
|
||||
#define __ASM __asm /*!< asm keyword for TI CCS Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __TASKING__ )
|
||||
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __CSMC__ )
|
||||
#define __packed
|
||||
#define __ASM _asm /*!< asm keyword for COSMIC Compiler */
|
||||
#define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#endif
|
||||
|
||||
/** __FPU_USED indicates whether an FPU is used or not.
|
||||
This core does not support an FPU at all
|
||||
*/
|
||||
#define __FPU_USED 0
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#if defined __TARGET_FPU_VFP
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
#if defined __ARMVFP__
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __TMS470__ )
|
||||
#if defined __TI__VFP_SUPPORT____
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __TASKING__ )
|
||||
#if defined __FPU_VFP__
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __CSMC__ ) /* Cosmic */
|
||||
#if ( __CSMC__ & 0x400) // FPU present for parser
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdint.h> /* standard types definitions */
|
||||
#include <core_cmInstr.h> /* Core Instruction Access */
|
||||
#include <core_cmFunc.h> /* Core Function Access */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM0PLUS_H_GENERIC */
|
||||
|
||||
#ifndef __CMSIS_GENERIC
|
||||
|
||||
#ifndef __CORE_CM0PLUS_H_DEPENDANT
|
||||
#define __CORE_CM0PLUS_H_DEPENDANT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* check device defines and use defaults */
|
||||
#if defined __CHECK_DEVICE_DEFINES
|
||||
#ifndef __CM0PLUS_REV
|
||||
#define __CM0PLUS_REV 0x0000
|
||||
#warning "__CM0PLUS_REV not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __MPU_PRESENT
|
||||
#define __MPU_PRESENT 0
|
||||
#warning "__MPU_PRESENT not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __VTOR_PRESENT
|
||||
#define __VTOR_PRESENT 0
|
||||
#warning "__VTOR_PRESENT not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __NVIC_PRIO_BITS
|
||||
#define __NVIC_PRIO_BITS 2
|
||||
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __Vendor_SysTickConfig
|
||||
#define __Vendor_SysTickConfig 0
|
||||
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* IO definitions (access restrictions to peripheral registers) */
|
||||
/**
|
||||
\defgroup CMSIS_glob_defs CMSIS Global Defines
|
||||
|
||||
<strong>IO Type Qualifiers</strong> are used
|
||||
\li to specify the access to peripheral variables.
|
||||
\li for automatic generation of peripheral register debug information.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define __I volatile /*!< Defines 'read only' permissions */
|
||||
#else
|
||||
#define __I volatile const /*!< Defines 'read only' permissions */
|
||||
#endif
|
||||
#define __O volatile /*!< Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
|
||||
/*@} end of group Cortex-M0+ */
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Register Abstraction
|
||||
Core Register contain:
|
||||
- Core Register
|
||||
- Core NVIC Register
|
||||
- Core SCB Register
|
||||
- Core SysTick Register
|
||||
- Core MPU Register
|
||||
******************************************************************************/
|
||||
/** \defgroup CMSIS_core_register Defines and Type Definitions
|
||||
\brief Type definitions and defines for Cortex-M processor based devices.
|
||||
*/
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_CORE Status and Control Registers
|
||||
\brief Core Register type definitions.
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Union type to access the Application Program Status Register (APSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#if (__CORTEX_M != 0x04)
|
||||
uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
|
||||
#else
|
||||
uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
|
||||
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
|
||||
uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
|
||||
#endif
|
||||
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
|
||||
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
|
||||
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
|
||||
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
|
||||
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} APSR_Type;
|
||||
|
||||
|
||||
/** \brief Union type to access the Interrupt Program Status Register (IPSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
|
||||
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} IPSR_Type;
|
||||
|
||||
|
||||
/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
|
||||
#if (__CORTEX_M != 0x04)
|
||||
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
|
||||
#else
|
||||
uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
|
||||
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
|
||||
uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
|
||||
#endif
|
||||
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
|
||||
uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
|
||||
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
|
||||
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
|
||||
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
|
||||
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
|
||||
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} xPSR_Type;
|
||||
|
||||
|
||||
/** \brief Union type to access the Control Registers (CONTROL).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
|
||||
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
|
||||
uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
|
||||
uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} CONTROL_Type;
|
||||
|
||||
/*@} end of group CMSIS_CORE */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
|
||||
\brief Type definitions for the NVIC Registers
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[31];
|
||||
__IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[31];
|
||||
__IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[31];
|
||||
__IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[31];
|
||||
uint32_t RESERVED4[64];
|
||||
__IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
|
||||
} NVIC_Type;
|
||||
|
||||
/*@} end of group CMSIS_NVIC */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_SCB System Control Block (SCB)
|
||||
\brief Type definitions for the System Control Block Registers
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the System Control Block (SCB).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
|
||||
__IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
|
||||
#if (__VTOR_PRESENT == 1)
|
||||
__IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
|
||||
#else
|
||||
uint32_t RESERVED0;
|
||||
#endif
|
||||
__IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
|
||||
__IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
|
||||
__IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
|
||||
uint32_t RESERVED1;
|
||||
__IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
|
||||
__IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
|
||||
} SCB_Type;
|
||||
|
||||
/* SCB CPUID Register Definitions */
|
||||
#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
|
||||
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
|
||||
|
||||
#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
|
||||
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
|
||||
|
||||
#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
|
||||
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
|
||||
|
||||
#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
|
||||
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
|
||||
|
||||
#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
|
||||
#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
|
||||
|
||||
/* SCB Interrupt Control State Register Definitions */
|
||||
#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
|
||||
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
|
||||
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
|
||||
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
|
||||
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
|
||||
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
|
||||
|
||||
#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
|
||||
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
|
||||
|
||||
#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
|
||||
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
|
||||
|
||||
#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
|
||||
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
|
||||
|
||||
#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
|
||||
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
|
||||
|
||||
#if (__VTOR_PRESENT == 1)
|
||||
/* SCB Interrupt Control State Register Definitions */
|
||||
#define SCB_VTOR_TBLOFF_Pos 8 /*!< SCB VTOR: TBLOFF Position */
|
||||
#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
|
||||
#endif
|
||||
|
||||
/* SCB Application Interrupt and Reset Control Register Definitions */
|
||||
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
|
||||
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
|
||||
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
|
||||
|
||||
#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
|
||||
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
|
||||
|
||||
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
|
||||
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
|
||||
|
||||
/* SCB System Control Register Definitions */
|
||||
#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
|
||||
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
|
||||
|
||||
#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
|
||||
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
|
||||
|
||||
#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
|
||||
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
|
||||
|
||||
/* SCB Configuration Control Register Definitions */
|
||||
#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
|
||||
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
|
||||
|
||||
#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
|
||||
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
|
||||
|
||||
/* SCB System Handler Control and State Register Definitions */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
|
||||
|
||||
/*@} end of group CMSIS_SCB */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
|
||||
\brief Type definitions for the System Timer Registers.
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the System Timer (SysTick).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
|
||||
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
|
||||
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
|
||||
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
|
||||
} SysTick_Type;
|
||||
|
||||
/* SysTick Control / Status Register Definitions */
|
||||
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
|
||||
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
|
||||
|
||||
#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
|
||||
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
|
||||
|
||||
#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
|
||||
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
|
||||
|
||||
#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
|
||||
#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
|
||||
|
||||
/* SysTick Reload Register Definitions */
|
||||
#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
|
||||
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
|
||||
|
||||
/* SysTick Current Register Definitions */
|
||||
#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
|
||||
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
|
||||
|
||||
/* SysTick Calibration Register Definitions */
|
||||
#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
|
||||
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
|
||||
|
||||
#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
|
||||
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
|
||||
|
||||
#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
|
||||
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_CALIB_TENMS_Pos) /*!< SysTick CALIB: TENMS Mask */
|
||||
|
||||
/*@} end of group CMSIS_SysTick */
|
||||
|
||||
#if (__MPU_PRESENT == 1)
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
|
||||
\brief Type definitions for the Memory Protection Unit (MPU)
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the Memory Protection Unit (MPU).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
|
||||
__IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
|
||||
__IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
|
||||
__IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
|
||||
__IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
|
||||
} MPU_Type;
|
||||
|
||||
/* MPU Type Register */
|
||||
#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */
|
||||
#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
|
||||
|
||||
#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */
|
||||
#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
|
||||
|
||||
#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */
|
||||
#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */
|
||||
|
||||
/* MPU Control Register */
|
||||
#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */
|
||||
#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
|
||||
|
||||
#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */
|
||||
#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
|
||||
|
||||
#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */
|
||||
#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */
|
||||
|
||||
/* MPU Region Number Register */
|
||||
#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */
|
||||
#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */
|
||||
|
||||
/* MPU Region Base Address Register */
|
||||
#define MPU_RBAR_ADDR_Pos 8 /*!< MPU RBAR: ADDR Position */
|
||||
#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
|
||||
|
||||
#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */
|
||||
#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
|
||||
|
||||
#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */
|
||||
#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */
|
||||
|
||||
/* MPU Region Attribute and Size Register */
|
||||
#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */
|
||||
#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
|
||||
|
||||
#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */
|
||||
#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
|
||||
|
||||
#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */
|
||||
#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
|
||||
|
||||
#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */
|
||||
#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
|
||||
|
||||
#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */
|
||||
#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
|
||||
|
||||
#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */
|
||||
#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
|
||||
|
||||
#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */
|
||||
#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
|
||||
|
||||
#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */
|
||||
#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
|
||||
|
||||
#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */
|
||||
#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
|
||||
|
||||
#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */
|
||||
#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */
|
||||
|
||||
/*@} end of group CMSIS_MPU */
|
||||
#endif
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
|
||||
\brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR)
|
||||
are only accessible over DAP and not via processor. Therefore
|
||||
they are not covered by the Cortex-M0 header file.
|
||||
@{
|
||||
*/
|
||||
/*@} end of group CMSIS_CoreDebug */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_core_base Core Definitions
|
||||
\brief Definitions for base addresses, unions, and structures.
|
||||
@{
|
||||
*/
|
||||
|
||||
/* Memory mapping of Cortex-M0+ Hardware */
|
||||
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
|
||||
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
|
||||
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
|
||||
|
||||
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
|
||||
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
|
||||
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
|
||||
|
||||
#if (__MPU_PRESENT == 1)
|
||||
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
|
||||
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
|
||||
#endif
|
||||
|
||||
/*@} */
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Hardware Abstraction Layer
|
||||
Core Function Interface contains:
|
||||
- Core NVIC Functions
|
||||
- Core SysTick Functions
|
||||
- Core Register Access Functions
|
||||
******************************************************************************/
|
||||
/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ########################## NVIC functions #################################### */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
|
||||
\brief Functions that manage interrupts and exceptions via the NVIC.
|
||||
@{
|
||||
*/
|
||||
|
||||
/* Interrupt Priorities are WORD accessible only under ARMv6M */
|
||||
/* The following MACROS handle generation of the register offset and byte masks */
|
||||
#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
|
||||
#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
|
||||
#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
|
||||
|
||||
|
||||
/** \brief Enable External Interrupt
|
||||
|
||||
The function enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Disable External Interrupt
|
||||
|
||||
The function disables a device-specific interrupt in the NVIC interrupt controller.
|
||||
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Pending Interrupt
|
||||
|
||||
The function reads the pending register in the NVIC and returns the pending bit
|
||||
for the specified interrupt.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
|
||||
\return 0 Interrupt status is not pending.
|
||||
\return 1 Interrupt status is pending.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Pending Interrupt
|
||||
|
||||
The function sets the pending bit of an external interrupt.
|
||||
|
||||
\param [in] IRQn Interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Clear Pending Interrupt
|
||||
|
||||
The function clears the pending bit of an external interrupt.
|
||||
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Interrupt Priority
|
||||
|
||||
The function sets the priority of an interrupt.
|
||||
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
if(IRQn < 0) {
|
||||
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
|
||||
else {
|
||||
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Interrupt Priority
|
||||
|
||||
The function reads the priority of an interrupt. The interrupt
|
||||
number can be positive to specify an external (device specific)
|
||||
interrupt, or negative to specify an internal (core) interrupt.
|
||||
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return Interrupt Priority. Value is aligned automatically to the implemented
|
||||
priority bits of the microcontroller.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
|
||||
{
|
||||
|
||||
if(IRQn < 0) {
|
||||
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
|
||||
else {
|
||||
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
|
||||
}
|
||||
|
||||
|
||||
/** \brief System Reset
|
||||
|
||||
The function initiates a system reset request to reset the MCU.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SystemReset(void)
|
||||
{
|
||||
__DSB(); /* Ensure all outstanding memory accesses included
|
||||
buffered write are completed before reset */
|
||||
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
|
||||
SCB_AIRCR_SYSRESETREQ_Msk);
|
||||
__DSB(); /* Ensure completion of memory access */
|
||||
while(1); /* wait until reset */
|
||||
}
|
||||
|
||||
/*@} end of CMSIS_Core_NVICFunctions */
|
||||
|
||||
|
||||
|
||||
/* ################################## SysTick function ############################################ */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
|
||||
\brief Functions that configure the System.
|
||||
@{
|
||||
*/
|
||||
|
||||
#if (__Vendor_SysTickConfig == 0)
|
||||
|
||||
/** \brief System Tick Configuration
|
||||
|
||||
The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
Counter is in free running mode to generate periodic interrupts.
|
||||
|
||||
\param [in] ticks Number of ticks between two interrupts.
|
||||
|
||||
\return 0 Function succeeded.
|
||||
\return 1 Function failed.
|
||||
|
||||
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
|
||||
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
|
||||
must contain a vendor-specific implementation of this function.
|
||||
|
||||
*/
|
||||
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
|
||||
{
|
||||
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
|
||||
|
||||
SysTick->LOAD = ticks - 1; /* set reload register */
|
||||
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
|
||||
SysTick->VAL = 0; /* Load the SysTick Counter Value */
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
|
||||
return (0); /* Function successful */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of CMSIS_Core_SysTickFunctions */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM0PLUS_H_DEPENDANT */
|
||||
|
||||
#endif /* __CMSIS_GENERIC */
|
||||
@@ -0,0 +1,637 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmFunc.h
|
||||
* @brief CMSIS Cortex-M Core Function Access Header File
|
||||
* @version V4.00
|
||||
* @date 28. August 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __CORE_CMFUNC_H
|
||||
#define __CORE_CMFUNC_H
|
||||
|
||||
|
||||
/* ########################### Core Function Access ########################### */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
|
||||
#if (__ARMCC_VERSION < 400677)
|
||||
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
|
||||
#endif
|
||||
|
||||
/* intrinsic void __enable_irq(); */
|
||||
/* intrinsic void __disable_irq(); */
|
||||
|
||||
/** \brief Get Control Register
|
||||
|
||||
This function returns the content of the Control Register.
|
||||
|
||||
\return Control Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
return(__regControl);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Control Register
|
||||
|
||||
This function writes the given value to the Control Register.
|
||||
|
||||
\param [in] control Control Register value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
__regControl = control;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get IPSR Register
|
||||
|
||||
This function returns the content of the IPSR Register.
|
||||
|
||||
\return IPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_IPSR(void)
|
||||
{
|
||||
register uint32_t __regIPSR __ASM("ipsr");
|
||||
return(__regIPSR);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get APSR Register
|
||||
|
||||
This function returns the content of the APSR Register.
|
||||
|
||||
\return APSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
register uint32_t __regAPSR __ASM("apsr");
|
||||
return(__regAPSR);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get xPSR Register
|
||||
|
||||
This function returns the content of the xPSR Register.
|
||||
|
||||
\return xPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_xPSR(void)
|
||||
{
|
||||
register uint32_t __regXPSR __ASM("xpsr");
|
||||
return(__regXPSR);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Process Stack Pointer
|
||||
|
||||
This function returns the current value of the Process Stack Pointer (PSP).
|
||||
|
||||
\return PSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PSP(void)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
return(__regProcessStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Process Stack Pointer
|
||||
|
||||
This function assigns the given value to the Process Stack Pointer (PSP).
|
||||
|
||||
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
__regProcessStackPointer = topOfProcStack;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Main Stack Pointer
|
||||
|
||||
This function returns the current value of the Main Stack Pointer (MSP).
|
||||
|
||||
\return MSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
return(__regMainStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Main Stack Pointer
|
||||
|
||||
This function assigns the given value to the Main Stack Pointer (MSP).
|
||||
|
||||
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
__regMainStackPointer = topOfMainStack;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Priority Mask
|
||||
|
||||
This function returns the current state of the priority mask bit from the Priority Mask Register.
|
||||
|
||||
\return Priority Mask value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
return(__regPriMask);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Priority Mask
|
||||
|
||||
This function assigns the given value to the Priority Mask Register.
|
||||
|
||||
\param [in] priMask Priority Mask
|
||||
*/
|
||||
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
__regPriMask = (priMask);
|
||||
}
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)
|
||||
|
||||
/** \brief Enable FIQ
|
||||
|
||||
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __enable_fault_irq __enable_fiq
|
||||
|
||||
|
||||
/** \brief Disable FIQ
|
||||
|
||||
This function disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __disable_fault_irq __disable_fiq
|
||||
|
||||
|
||||
/** \brief Get Base Priority
|
||||
|
||||
This function returns the current value of the Base Priority register.
|
||||
|
||||
\return Base Priority register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
return(__regBasePri);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Base Priority
|
||||
|
||||
This function assigns the given value to the Base Priority register.
|
||||
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
__regBasePri = (basePri & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Fault Mask
|
||||
|
||||
This function returns the current value of the Fault Mask register.
|
||||
|
||||
\return Fault Mask register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
return(__regFaultMask);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Fault Mask
|
||||
|
||||
This function assigns the given value to the Fault Mask register.
|
||||
|
||||
\param [in] faultMask Fault Mask value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
__regFaultMask = (faultMask & (uint32_t)1);
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300) */
|
||||
|
||||
|
||||
#if (__CORTEX_M == 0x04) || (__CORTEX_M == 0x07)
|
||||
|
||||
/** \brief Get FPSCR
|
||||
|
||||
This function returns the current value of the Floating Point Status/Control register.
|
||||
|
||||
\return Floating Point Status/Control register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
return(__regfpscr);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set FPSCR
|
||||
|
||||
This function assigns the given value to the Floating Point Status/Control register.
|
||||
|
||||
\param [in] fpscr Floating Point Status/Control value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
__regfpscr = (fpscr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M == 0x04) || (__CORTEX_M == 0x07) */
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
|
||||
/** \brief Enable IRQ Interrupts
|
||||
|
||||
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsie i" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Disable IRQ Interrupts
|
||||
|
||||
This function disables IRQ interrupts by setting the I-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsid i" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Control Register
|
||||
|
||||
This function returns the content of the Control Register.
|
||||
|
||||
\return Control Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, control" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Control Register
|
||||
|
||||
This function writes the given value to the Control Register.
|
||||
|
||||
\param [in] control Control Register value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get IPSR Register
|
||||
|
||||
This function returns the content of the IPSR Register.
|
||||
|
||||
\return IPSR Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get APSR Register
|
||||
|
||||
This function returns the content of the APSR Register.
|
||||
|
||||
\return APSR Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get xPSR Register
|
||||
|
||||
This function returns the content of the xPSR Register.
|
||||
|
||||
\return xPSR Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Process Stack Pointer
|
||||
|
||||
This function returns the current value of the Process Stack Pointer (PSP).
|
||||
|
||||
\return PSP Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Process Stack Pointer
|
||||
|
||||
This function assigns the given value to the Process Stack Pointer (PSP).
|
||||
|
||||
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Main Stack Pointer
|
||||
|
||||
This function returns the current value of the Main Stack Pointer (MSP).
|
||||
|
||||
\return MSP Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Main Stack Pointer
|
||||
|
||||
This function assigns the given value to the Main Stack Pointer (MSP).
|
||||
|
||||
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Priority Mask
|
||||
|
||||
This function returns the current state of the priority mask bit from the Priority Mask Register.
|
||||
|
||||
\return Priority Mask value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, primask" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Priority Mask
|
||||
|
||||
This function assigns the given value to the Priority Mask Register.
|
||||
|
||||
\param [in] priMask Priority Mask
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
__ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
|
||||
}
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03)
|
||||
|
||||
/** \brief Enable FIQ
|
||||
|
||||
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsie f" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Disable FIQ
|
||||
|
||||
This function disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsid f" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Base Priority
|
||||
|
||||
This function returns the current value of the Base Priority register.
|
||||
|
||||
\return Base Priority register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Base Priority
|
||||
|
||||
This function assigns the given value to the Base Priority register.
|
||||
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
|
||||
{
|
||||
__ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Fault Mask
|
||||
|
||||
This function returns the current value of the Fault Mask register.
|
||||
|
||||
\return Fault Mask register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Fault Mask
|
||||
|
||||
This function assigns the given value to the Fault Mask register.
|
||||
|
||||
\param [in] faultMask Fault Mask value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
|
||||
#if (__CORTEX_M == 0x04) || (__CORTEX_M == 0x07)
|
||||
|
||||
/** \brief Get FPSCR
|
||||
|
||||
This function returns the current value of the Floating Point Status/Control register.
|
||||
|
||||
\return Floating Point Status/Control register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
uint32_t result;
|
||||
|
||||
/* Empty asm statement works as a scheduling barrier */
|
||||
__ASM volatile ("");
|
||||
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
|
||||
__ASM volatile ("");
|
||||
return(result);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set FPSCR
|
||||
|
||||
This function assigns the given value to the Floating Point Status/Control register.
|
||||
|
||||
\param [in] fpscr Floating Point Status/Control value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
/* Empty asm statement works as a scheduling barrier */
|
||||
__ASM volatile ("");
|
||||
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
|
||||
__ASM volatile ("");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M == 0x04) || (__CORTEX_M == 0x07) */
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
|
||||
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
|
||||
/* Cosmic specific functions */
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of CMSIS_Core_RegAccFunctions */
|
||||
|
||||
#endif /* __CORE_CMFUNC_H */
|
||||
@@ -0,0 +1,880 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmInstr.h
|
||||
* @brief CMSIS Cortex-M Core Instruction Access Header File
|
||||
* @version V4.00
|
||||
* @date 28. August 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __CORE_CMINSTR_H
|
||||
#define __CORE_CMINSTR_H
|
||||
|
||||
|
||||
/* ########################## Core Instruction Access ######################### */
|
||||
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||
Access to dedicated instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
|
||||
#if (__ARMCC_VERSION < 400677)
|
||||
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief No Operation
|
||||
|
||||
No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
#define __NOP __nop
|
||||
|
||||
|
||||
/** \brief Wait For Interrupt
|
||||
|
||||
Wait For Interrupt is a hint instruction that suspends execution
|
||||
until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFI __wfi
|
||||
|
||||
|
||||
/** \brief Wait For Event
|
||||
|
||||
Wait For Event is a hint instruction that permits the processor to enter
|
||||
a low-power state until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFE __wfe
|
||||
|
||||
|
||||
/** \brief Send Event
|
||||
|
||||
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||
*/
|
||||
#define __SEV __sev
|
||||
|
||||
|
||||
/** \brief Instruction Synchronization Barrier
|
||||
|
||||
Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or
|
||||
memory, after the instruction has been completed.
|
||||
*/
|
||||
#define __ISB() __isb(0xF)
|
||||
|
||||
|
||||
/** \brief Data Synchronization Barrier
|
||||
|
||||
This function acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
#define __DSB() __dsb(0xF)
|
||||
|
||||
|
||||
/** \brief Data Memory Barrier
|
||||
|
||||
This function ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
#define __DMB() __dmb(0xF)
|
||||
|
||||
|
||||
/** \brief Reverse byte order (32 bit)
|
||||
|
||||
This function reverses the byte order in integer value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#define __REV __rev
|
||||
|
||||
|
||||
/** \brief Reverse byte order (16 bit)
|
||||
|
||||
This function reverses the byte order in two unsigned short values.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
rev16 r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Reverse byte order in signed short value
|
||||
|
||||
This function reverses the byte order in a signed short value with sign extension to integer.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
|
||||
{
|
||||
revsh r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief Rotate Right in unsigned value (32 bit)
|
||||
|
||||
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
|
||||
\param [in] value Value to rotate
|
||||
\param [in] value Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#define __ROR __ror
|
||||
|
||||
|
||||
/** \brief Breakpoint
|
||||
|
||||
This function causes the processor to enter Debug state.
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
|
||||
\param [in] value is ignored by the processor.
|
||||
If required, a debugger can use it to store additional information about the breakpoint.
|
||||
*/
|
||||
#define __BKPT(value) __breakpoint(value)
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)
|
||||
|
||||
/** \brief Reverse bit order of value
|
||||
|
||||
This function reverses the bit order of the given value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#define __RBIT __rbit
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (8 bit)
|
||||
|
||||
This function executes a exclusive LDR instruction for 8 bit value.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (16 bit)
|
||||
|
||||
This function executes a exclusive LDR instruction for 16 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (32 bit)
|
||||
|
||||
This function executes a exclusive LDR instruction for 32 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
|
||||
|
||||
|
||||
/** \brief STR Exclusive (8 bit)
|
||||
|
||||
This function executes a exclusive STR instruction for 8 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#define __STREXB(value, ptr) __strex(value, ptr)
|
||||
|
||||
|
||||
/** \brief STR Exclusive (16 bit)
|
||||
|
||||
This function executes a exclusive STR instruction for 16 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#define __STREXH(value, ptr) __strex(value, ptr)
|
||||
|
||||
|
||||
/** \brief STR Exclusive (32 bit)
|
||||
|
||||
This function executes a exclusive STR instruction for 32 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#define __STREXW(value, ptr) __strex(value, ptr)
|
||||
|
||||
|
||||
/** \brief Remove the exclusive lock
|
||||
|
||||
This function removes the exclusive lock which is created by LDREX.
|
||||
|
||||
*/
|
||||
#define __CLREX __clrex
|
||||
|
||||
|
||||
/** \brief Signed Saturate
|
||||
|
||||
This function saturates a signed value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __SSAT __ssat
|
||||
|
||||
|
||||
/** \brief Unsigned Saturate
|
||||
|
||||
This function saturates an unsigned value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __USAT __usat
|
||||
|
||||
|
||||
/** \brief Count leading zeros
|
||||
|
||||
This function counts the number of leading zeros of a data value.
|
||||
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
#define __CLZ __clz
|
||||
|
||||
|
||||
/** \brief Rotate Right with Extend (32 bit)
|
||||
|
||||
This function moves each bit of a bitstring right by one bit. The carry input is shifted in at the left end of the bitstring.
|
||||
|
||||
\param [in] value Value to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
|
||||
{
|
||||
rrx r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief LDRT Unprivileged (8 bit)
|
||||
|
||||
This function executes a Unprivileged LDRT instruction for 8 bit value.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
|
||||
|
||||
|
||||
/** \brief LDRT Unprivileged (16 bit)
|
||||
|
||||
This function executes a Unprivileged LDRT instruction for 16 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
|
||||
|
||||
|
||||
/** \brief LDRT Unprivileged (32 bit)
|
||||
|
||||
This function executes a Unprivileged LDRT instruction for 32 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
|
||||
|
||||
|
||||
/** \brief STRT Unprivileged (8 bit)
|
||||
|
||||
This function executes a Unprivileged STRT instruction for 8 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRBT(value, ptr) __strt(value, ptr)
|
||||
|
||||
|
||||
/** \brief STRT Unprivileged (16 bit)
|
||||
|
||||
This function executes a Unprivileged STRT instruction for 16 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRHT(value, ptr) __strt(value, ptr)
|
||||
|
||||
|
||||
/** \brief STRT Unprivileged (32 bit)
|
||||
|
||||
This function executes a Unprivileged STRT instruction for 32 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRT(value, ptr) __strt(value, ptr)
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300) */
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
|
||||
/* Define macros for porting to both thumb1 and thumb2.
|
||||
* For thumb1, use low register (r0-r7), specified by constrant "l"
|
||||
* Otherwise, use general registers, specified by constrant "r" */
|
||||
#if defined (__thumb__) && !defined (__thumb2__)
|
||||
#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
|
||||
#define __CMSIS_GCC_USE_REG(r) "l" (r)
|
||||
#else
|
||||
#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
|
||||
#define __CMSIS_GCC_USE_REG(r) "r" (r)
|
||||
#endif
|
||||
|
||||
/** \brief No Operation
|
||||
|
||||
No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
|
||||
{
|
||||
__ASM volatile ("nop");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Wait For Interrupt
|
||||
|
||||
Wait For Interrupt is a hint instruction that suspends execution
|
||||
until one of a number of events occurs.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
|
||||
{
|
||||
__ASM volatile ("wfi");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Wait For Event
|
||||
|
||||
Wait For Event is a hint instruction that permits the processor to enter
|
||||
a low-power state until one of a number of events occurs.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
|
||||
{
|
||||
__ASM volatile ("wfe");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Send Event
|
||||
|
||||
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
|
||||
{
|
||||
__ASM volatile ("sev");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Instruction Synchronization Barrier
|
||||
|
||||
Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or
|
||||
memory, after the instruction has been completed.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
|
||||
{
|
||||
__ASM volatile ("isb");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Data Synchronization Barrier
|
||||
|
||||
This function acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
|
||||
{
|
||||
__ASM volatile ("dsb");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Data Memory Barrier
|
||||
|
||||
This function ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
|
||||
{
|
||||
__ASM volatile ("dmb");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Reverse byte order (32 bit)
|
||||
|
||||
This function reverses the byte order in integer value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
|
||||
{
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
return __builtin_bswap32(value);
|
||||
#else
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Reverse byte order (16 bit)
|
||||
|
||||
This function reverses the byte order in two unsigned short values.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Reverse byte order in signed short value
|
||||
|
||||
This function reverses the byte order in a signed short value with sign extension to integer.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
|
||||
{
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
return (short)__builtin_bswap16(value);
|
||||
#else
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Rotate Right in unsigned value (32 bit)
|
||||
|
||||
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
|
||||
\param [in] value Value to rotate
|
||||
\param [in] value Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
return (op1 >> op2) | (op1 << (32 - op2));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Breakpoint
|
||||
|
||||
This function causes the processor to enter Debug state.
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
|
||||
\param [in] value is ignored by the processor.
|
||||
If required, a debugger can use it to store additional information about the breakpoint.
|
||||
*/
|
||||
#define __BKPT(value) __ASM volatile ("bkpt "#value)
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)
|
||||
|
||||
/** \brief Reverse bit order of value
|
||||
|
||||
This function reverses the bit order of the given value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (8 bit)
|
||||
|
||||
This function executes a exclusive LDR instruction for 8 bit value.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
__ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
#else
|
||||
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
|
||||
accepted by assembler. So has to use following less efficient pattern.
|
||||
*/
|
||||
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
|
||||
#endif
|
||||
return ((uint8_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (16 bit)
|
||||
|
||||
This function executes a exclusive LDR instruction for 16 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
__ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
#else
|
||||
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
|
||||
accepted by assembler. So has to use following less efficient pattern.
|
||||
*/
|
||||
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
|
||||
#endif
|
||||
return ((uint16_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (32 bit)
|
||||
|
||||
This function executes a exclusive LDR instruction for 32 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STR Exclusive (8 bit)
|
||||
|
||||
This function executes a exclusive STR instruction for 8 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STR Exclusive (16 bit)
|
||||
|
||||
This function executes a exclusive STR instruction for 16 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STR Exclusive (32 bit)
|
||||
|
||||
This function executes a exclusive STR instruction for 32 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Remove the exclusive lock
|
||||
|
||||
This function removes the exclusive lock which is created by LDREX.
|
||||
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
|
||||
{
|
||||
__ASM volatile ("clrex" ::: "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Signed Saturate
|
||||
|
||||
This function saturates a signed value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __SSAT(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
|
||||
/** \brief Unsigned Saturate
|
||||
|
||||
This function saturates an unsigned value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __USAT(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
|
||||
/** \brief Count leading zeros
|
||||
|
||||
This function counts the number of leading zeros of a data value.
|
||||
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
|
||||
return ((uint8_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief Rotate Right with Extend (32 bit)
|
||||
|
||||
This function moves each bit of a bitstring right by one bit. The carry input is shifted in at the left end of the bitstring.
|
||||
|
||||
\param [in] value Value to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RRX(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDRT Unprivileged (8 bit)
|
||||
|
||||
This function executes a Unprivileged LDRT instruction for 8 bit value.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
__ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
#else
|
||||
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
|
||||
accepted by assembler. So has to use following less efficient pattern.
|
||||
*/
|
||||
__ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
|
||||
#endif
|
||||
return ((uint8_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDRT Unprivileged (16 bit)
|
||||
|
||||
This function executes a Unprivileged LDRT instruction for 16 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
__ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
#else
|
||||
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
|
||||
accepted by assembler. So has to use following less efficient pattern.
|
||||
*/
|
||||
__ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
|
||||
#endif
|
||||
return ((uint16_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDRT Unprivileged (32 bit)
|
||||
|
||||
This function executes a Unprivileged LDRT instruction for 32 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STRT Unprivileged (8 bit)
|
||||
|
||||
This function executes a Unprivileged STRT instruction for 8 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr)
|
||||
{
|
||||
__ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) );
|
||||
}
|
||||
|
||||
|
||||
/** \brief STRT Unprivileged (16 bit)
|
||||
|
||||
This function executes a Unprivileged STRT instruction for 16 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr)
|
||||
{
|
||||
__ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) );
|
||||
}
|
||||
|
||||
|
||||
/** \brief STRT Unprivileged (32 bit)
|
||||
|
||||
This function executes a Unprivileged STRT instruction for 32 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr)
|
||||
{
|
||||
__ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) );
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300) */
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
|
||||
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
|
||||
/* Cosmic specific functions */
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
|
||||
|
||||
#endif /* __CORE_CMINSTR_H */
|
||||
@@ -0,0 +1,697 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmSimd.h
|
||||
* @brief CMSIS Cortex-M SIMD Header File
|
||||
* @version V4.00
|
||||
* @date 22. August 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CMSIMD_H
|
||||
#define __CORE_CMSIMD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Hardware Abstraction Layer
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
#define __SADD8 __sadd8
|
||||
#define __QADD8 __qadd8
|
||||
#define __SHADD8 __shadd8
|
||||
#define __UADD8 __uadd8
|
||||
#define __UQADD8 __uqadd8
|
||||
#define __UHADD8 __uhadd8
|
||||
#define __SSUB8 __ssub8
|
||||
#define __QSUB8 __qsub8
|
||||
#define __SHSUB8 __shsub8
|
||||
#define __USUB8 __usub8
|
||||
#define __UQSUB8 __uqsub8
|
||||
#define __UHSUB8 __uhsub8
|
||||
#define __SADD16 __sadd16
|
||||
#define __QADD16 __qadd16
|
||||
#define __SHADD16 __shadd16
|
||||
#define __UADD16 __uadd16
|
||||
#define __UQADD16 __uqadd16
|
||||
#define __UHADD16 __uhadd16
|
||||
#define __SSUB16 __ssub16
|
||||
#define __QSUB16 __qsub16
|
||||
#define __SHSUB16 __shsub16
|
||||
#define __USUB16 __usub16
|
||||
#define __UQSUB16 __uqsub16
|
||||
#define __UHSUB16 __uhsub16
|
||||
#define __SASX __sasx
|
||||
#define __QASX __qasx
|
||||
#define __SHASX __shasx
|
||||
#define __UASX __uasx
|
||||
#define __UQASX __uqasx
|
||||
#define __UHASX __uhasx
|
||||
#define __SSAX __ssax
|
||||
#define __QSAX __qsax
|
||||
#define __SHSAX __shsax
|
||||
#define __USAX __usax
|
||||
#define __UQSAX __uqsax
|
||||
#define __UHSAX __uhsax
|
||||
#define __USAD8 __usad8
|
||||
#define __USADA8 __usada8
|
||||
#define __SSAT16 __ssat16
|
||||
#define __USAT16 __usat16
|
||||
#define __UXTB16 __uxtb16
|
||||
#define __UXTAB16 __uxtab16
|
||||
#define __SXTB16 __sxtb16
|
||||
#define __SXTAB16 __sxtab16
|
||||
#define __SMUAD __smuad
|
||||
#define __SMUADX __smuadx
|
||||
#define __SMLAD __smlad
|
||||
#define __SMLADX __smladx
|
||||
#define __SMLALD __smlald
|
||||
#define __SMLALDX __smlaldx
|
||||
#define __SMUSD __smusd
|
||||
#define __SMUSDX __smusdx
|
||||
#define __SMLSD __smlsd
|
||||
#define __SMLSDX __smlsdx
|
||||
#define __SMLSLD __smlsld
|
||||
#define __SMLSLDX __smlsldx
|
||||
#define __SEL __sel
|
||||
#define __QADD __qadd
|
||||
#define __QSUB __qsub
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
|
||||
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
|
||||
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
|
||||
|
||||
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
|
||||
((int64_t)(ARG3) << 32) ) >> 32))
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __SSAT16(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
#define __USAT16(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
|
||||
__ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
|
||||
if (ARG3 == 0) \
|
||||
__ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
|
||||
else \
|
||||
__ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
__ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
/* not yet supported */
|
||||
|
||||
|
||||
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
|
||||
/* Cosmic specific functions */
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CMSIMD_H */
|
||||
@@ -0,0 +1,39 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide serial Input/Output routines.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#include "common.h"
|
||||
#include "uart.h"
|
||||
#include "stdio.h"
|
||||
|
||||
//********************************************************************/
|
||||
char
|
||||
in_char (void)
|
||||
{
|
||||
return UART_GetChar(TERM_PORT);
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
out_char (char ch)
|
||||
{
|
||||
UART_PutChar(TERM_PORT, ch);
|
||||
}
|
||||
/********************************************************************/
|
||||
int
|
||||
char_present (void)
|
||||
{
|
||||
return UART_CharPresent(TERM_PORT);
|
||||
}
|
||||
|
||||
#ifdef KEIL
|
||||
/********************************************************************/
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
out_char((char)ch);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,30 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide serial Input/Output routines.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _IO_H
|
||||
#define _IO_H
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
char
|
||||
in_char(void);
|
||||
|
||||
void
|
||||
out_char(char);
|
||||
|
||||
int
|
||||
char_present(void);
|
||||
|
||||
int
|
||||
printf(const char *, ... );
|
||||
|
||||
int
|
||||
sprintf(char *, const char *, ... );
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,211 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide general-purpose memory testing functions.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#include "memtest.h"
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Function: memTestDataBus()
|
||||
*
|
||||
* Description: Test the data bus wiring in a memory region by
|
||||
* performing a walking 1's test at a fixed address
|
||||
* within that region. The address (and hence the
|
||||
* memory region) is selected by the caller.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Returns: 0 if the test succeeds.
|
||||
* A non-zero result is the first pattern that failed.
|
||||
*
|
||||
**********************************************************************/
|
||||
datum
|
||||
memTestDataBus(volatile datum * address)
|
||||
{
|
||||
datum pattern;
|
||||
|
||||
|
||||
/*
|
||||
* Perform a walking 1's test at the given address.
|
||||
*/
|
||||
for (pattern = 1; pattern != 0; pattern <<= 1)
|
||||
{
|
||||
/*
|
||||
* Write the test pattern.
|
||||
*/
|
||||
*address = pattern;
|
||||
|
||||
/*
|
||||
* Read it back (immediately is okay for this test).
|
||||
*/
|
||||
if (*address != pattern)
|
||||
{
|
||||
return (pattern);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
} /* memTestDataBus() */
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Function: memTestAddressBus()
|
||||
*
|
||||
* Description: Test the address bus wiring in a memory region by
|
||||
* performing a walking 1's test on the relevant bits
|
||||
* of the address and checking for aliasing. This test
|
||||
* will find single-bit address failures such as stuck
|
||||
* -high, stuck-low, and shorted pins. The base address
|
||||
* and size of the region are selected by the caller.
|
||||
*
|
||||
* Notes: For best results, the selected base address should
|
||||
* have enough LSB 0's to guarantee single address bit
|
||||
* changes. For example, to test a 64-Kbyte region,
|
||||
* select a base address on a 64-Kbyte boundary. Also,
|
||||
* select the region size as a power-of-two--if at all
|
||||
* possible.
|
||||
*
|
||||
* Returns: NULL if the test succeeds.
|
||||
* A non-zero result is the first address at which an
|
||||
* aliasing problem was uncovered. By examining the
|
||||
* contents of memory, it may be possible to gather
|
||||
* additional information about the problem.
|
||||
*
|
||||
**********************************************************************/
|
||||
datum *
|
||||
memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes)
|
||||
{
|
||||
unsigned long addressMask = (nBytes/sizeof(datum) - 1);
|
||||
unsigned long offset;
|
||||
unsigned long testOffset;
|
||||
|
||||
datum pattern = (datum) 0xAAAAAAAA;
|
||||
datum antipattern = (datum) 0x55555555;
|
||||
|
||||
|
||||
/*
|
||||
* Write the default pattern at each of the power-of-two offsets.
|
||||
*/
|
||||
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
|
||||
{
|
||||
baseAddress[offset] = pattern;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for address bits stuck high.
|
||||
*/
|
||||
testOffset = 0;
|
||||
baseAddress[testOffset] = antipattern;
|
||||
|
||||
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
|
||||
{
|
||||
if (baseAddress[offset] != pattern)
|
||||
{
|
||||
return ((datum *) &baseAddress[offset]);
|
||||
}
|
||||
}
|
||||
|
||||
baseAddress[testOffset] = pattern;
|
||||
|
||||
/*
|
||||
* Check for address bits stuck low or shorted.
|
||||
*/
|
||||
for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
|
||||
{
|
||||
baseAddress[testOffset] = antipattern;
|
||||
|
||||
if (baseAddress[0] != pattern)
|
||||
{
|
||||
return ((datum *) &baseAddress[testOffset]);
|
||||
}
|
||||
|
||||
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
|
||||
{
|
||||
if ((baseAddress[offset] != pattern) && (offset != testOffset))
|
||||
{
|
||||
return ((datum *) &baseAddress[testOffset]);
|
||||
}
|
||||
}
|
||||
|
||||
baseAddress[testOffset] = pattern;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
|
||||
} /* memTestAddressBus() */
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Function: memTestDevice()
|
||||
*
|
||||
* Description: Test the integrity of a physical memory device by
|
||||
* performing an increment/decrement test over the
|
||||
* entire region. In the process every storage bit
|
||||
* in the device is tested as a zero and a one. The
|
||||
* base address and the size of the region are
|
||||
* selected by the caller.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Returns: NULL if the test succeeds.
|
||||
*
|
||||
* A non-zero result is the first address at which an
|
||||
* incorrect value was read back. By examining the
|
||||
* contents of memory, it may be possible to gather
|
||||
* additional information about the problem.
|
||||
*
|
||||
**********************************************************************/
|
||||
datum *
|
||||
memTestDevice(volatile datum * baseAddress, unsigned long nBytes)
|
||||
{
|
||||
unsigned long offset;
|
||||
unsigned long nWords = nBytes / sizeof(datum);
|
||||
|
||||
datum pattern;
|
||||
datum antipattern;
|
||||
|
||||
|
||||
/*
|
||||
* Fill memory with a known pattern.
|
||||
*/
|
||||
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
|
||||
{
|
||||
baseAddress[offset] = pattern;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check each location and invert it for the second pass.
|
||||
*/
|
||||
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
|
||||
{
|
||||
if (baseAddress[offset] != pattern)
|
||||
{
|
||||
return ((datum *) &baseAddress[offset]);
|
||||
}
|
||||
|
||||
antipattern = ~pattern;
|
||||
baseAddress[offset] = antipattern;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check each location for the inverted pattern and zero it.
|
||||
*/
|
||||
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
|
||||
{
|
||||
antipattern = ~pattern;
|
||||
if (baseAddress[offset] != antipattern)
|
||||
{
|
||||
return ((datum *) &baseAddress[offset]);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
|
||||
} /* memTestDevice() */
|
||||
@@ -0,0 +1,32 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide general-purpose memory testing functions.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _memtest_h
|
||||
#define _memtest_h
|
||||
|
||||
|
||||
/*
|
||||
* Define NULL pointer value.
|
||||
*/
|
||||
#ifndef NULL
|
||||
#define NULL (void *) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the data bus width.
|
||||
*/
|
||||
typedef unsigned long datum;
|
||||
|
||||
/*
|
||||
* Function prototypes.
|
||||
*/
|
||||
datum memTestDataBus(volatile datum * address);
|
||||
datum * memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes);
|
||||
datum * memTestDevice(volatile datum * baseAddress, unsigned long nBytes);
|
||||
|
||||
|
||||
#endif /* _memtest_h */
|
||||
|
||||
@@ -0,0 +1,625 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* @brief provide the standard C library routine printf(), but without all the baggage.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int dest;
|
||||
void (*func)(char);
|
||||
char *loc;
|
||||
} PRINTK_INFO;
|
||||
|
||||
int
|
||||
printk (PRINTK_INFO *, const char *, va_list);
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#define DEST_CONSOLE (1)
|
||||
#define DEST_STRING (2)
|
||||
|
||||
#define FLAGS_MINUS (0x01)
|
||||
#define FLAGS_PLUS (0x02)
|
||||
#define FLAGS_SPACE (0x04)
|
||||
#define FLAGS_ZERO (0x08)
|
||||
#define FLAGS_POUND (0x10)
|
||||
|
||||
#define IS_FLAG_MINUS(a) (a & FLAGS_MINUS)
|
||||
#define IS_FLAG_PLUS(a) (a & FLAGS_PLUS)
|
||||
#define IS_FLAG_SPACE(a) (a & FLAGS_SPACE)
|
||||
#define IS_FLAG_ZERO(a) (a & FLAGS_ZERO)
|
||||
#define IS_FLAG_POUND(a) (a & FLAGS_POUND)
|
||||
|
||||
#define LENMOD_h (0x01)
|
||||
#define LENMOD_l (0x02)
|
||||
#define LENMOD_L (0x04)
|
||||
|
||||
#define IS_LENMOD_h(a) (a & LENMOD_h)
|
||||
#define IS_LENMOD_l(a) (a & LENMOD_l)
|
||||
#define IS_LENMOD_L(a) (a & LENMOD_L)
|
||||
|
||||
#define FMT_d (0x0001)
|
||||
#define FMT_o (0x0002)
|
||||
#define FMT_x (0x0004)
|
||||
#define FMT_X (0x0008)
|
||||
#define FMT_u (0x0010)
|
||||
#define FMT_c (0x0020)
|
||||
#define FMT_s (0x0040)
|
||||
#define FMT_p (0x0080)
|
||||
#define FMT_n (0x0100)
|
||||
|
||||
#define IS_FMT_d(a) (a & FMT_d)
|
||||
#define IS_FMT_o(a) (a & FMT_o)
|
||||
#define IS_FMT_x(a) (a & FMT_x)
|
||||
#define IS_FMT_X(a) (a & FMT_X)
|
||||
#define IS_FMT_u(a) (a & FMT_u)
|
||||
#define IS_FMT_c(a) (a & FMT_c)
|
||||
#define IS_FMT_s(a) (a & FMT_s)
|
||||
#define IS_FMT_p(a) (a & FMT_p)
|
||||
#define IS_FMT_n(a) (a & FMT_n)
|
||||
|
||||
/********************************************************************/
|
||||
static void
|
||||
printk_putc (int c, int *count, PRINTK_INFO *info)
|
||||
{
|
||||
switch (info->dest)
|
||||
{
|
||||
case DEST_CONSOLE:
|
||||
info->func((char)c);
|
||||
break;
|
||||
case DEST_STRING:
|
||||
*(info->loc) = (unsigned char)c;
|
||||
++(info->loc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*count += 1;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static int
|
||||
printk_mknumstr (char *numstr, void *nump, int neg, int radix)
|
||||
{
|
||||
int a,b,c;
|
||||
unsigned int ua,ub,uc;
|
||||
|
||||
int nlen;
|
||||
char *nstrp;
|
||||
|
||||
nlen = 0;
|
||||
nstrp = numstr;
|
||||
*nstrp++ = '\0';
|
||||
|
||||
if (neg)
|
||||
{
|
||||
a = *(int *)nump;
|
||||
if (a == 0)
|
||||
{
|
||||
*nstrp = '0';
|
||||
++nlen;
|
||||
goto done;
|
||||
}
|
||||
while (a != 0)
|
||||
{
|
||||
b = (int)a / (int)radix;
|
||||
c = (int)a - ((int)b * (int)radix);
|
||||
if (c < 0)
|
||||
{
|
||||
c = ~c + 1 + '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
c = c + '0';
|
||||
}
|
||||
a = b;
|
||||
*nstrp++ = (char)c;
|
||||
++nlen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ua = *(unsigned int *)nump;
|
||||
if (ua == 0)
|
||||
{
|
||||
*nstrp = '0';
|
||||
++nlen;
|
||||
goto done;
|
||||
}
|
||||
while (ua != 0)
|
||||
{
|
||||
ub = (unsigned int)ua / (unsigned int)radix;
|
||||
uc = (unsigned int)ua - ((unsigned int)ub * (unsigned int)radix);
|
||||
if (uc < 10)
|
||||
{
|
||||
uc = uc + '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
uc = uc - 10 + 'A';
|
||||
}
|
||||
ua = ub;
|
||||
*nstrp++ = (char)uc;
|
||||
++nlen;
|
||||
}
|
||||
}
|
||||
done:
|
||||
return nlen;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static void
|
||||
printk_pad_zero (int curlen, int field_width, int *count, PRINTK_INFO *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = curlen; i < field_width; i++)
|
||||
{
|
||||
printk_putc('0',count, info);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static void
|
||||
printk_pad_space (int curlen, int field_width, int *count, PRINTK_INFO *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = curlen; i < field_width; i++)
|
||||
{
|
||||
printk_putc(' ',count, info);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int
|
||||
printk (PRINTK_INFO *info, const char *fmt, va_list ap)
|
||||
{
|
||||
/* va_list ap; */
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
char vstr[33];
|
||||
char *vstrp;
|
||||
int vlen;
|
||||
|
||||
int done;
|
||||
int count = 0;
|
||||
|
||||
int flags_used;
|
||||
int field_width;
|
||||
#if 0
|
||||
int precision_used;
|
||||
int precision_width;
|
||||
int length_modifier;
|
||||
#endif
|
||||
|
||||
int ival;
|
||||
int schar, dschar;
|
||||
int *ivalp;
|
||||
char *sval;
|
||||
int cval;
|
||||
unsigned int uval;
|
||||
|
||||
/*
|
||||
* Start parsing apart the format string and display appropriate
|
||||
* formats and data.
|
||||
*/
|
||||
for (p = (char *)fmt; (c = *p) != 0; p++)
|
||||
{
|
||||
/*
|
||||
* All formats begin with a '%' marker. Special chars like
|
||||
* '\n' or '\t' are normally converted to the appropriate
|
||||
* character by the __compiler__. Thus, no need for this
|
||||
* routine to account for the '\' character.
|
||||
*/
|
||||
if (c != '%')
|
||||
{
|
||||
/*
|
||||
* This needs to be replaced with something like
|
||||
* 'out_char()' or call an OS routine.
|
||||
*/
|
||||
#ifndef UNIX_DEBUG
|
||||
if (c != '\n')
|
||||
{
|
||||
printk_putc(c, &count, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk_putc(0x0D /* CR */, &count, info);
|
||||
printk_putc(0x0A /* LF */, &count, info);
|
||||
}
|
||||
#else
|
||||
printk_putc(c, &count, info);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* By using 'continue', the next iteration of the loop
|
||||
* is used, skipping the code that follows.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* First check for specification modifier flags.
|
||||
*/
|
||||
flags_used = 0;
|
||||
done = FALSE;
|
||||
while (!done)
|
||||
{
|
||||
switch (/* c = */ *++p)
|
||||
{
|
||||
case '-':
|
||||
flags_used |= FLAGS_MINUS;
|
||||
break;
|
||||
case '+':
|
||||
flags_used |= FLAGS_PLUS;
|
||||
break;
|
||||
case ' ':
|
||||
flags_used |= FLAGS_SPACE;
|
||||
break;
|
||||
case '0':
|
||||
flags_used |= FLAGS_ZERO;
|
||||
break;
|
||||
case '#':
|
||||
flags_used |= FLAGS_POUND;
|
||||
break;
|
||||
default:
|
||||
/* we've gone one char too far */
|
||||
--p;
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Next check for minimum field width.
|
||||
*/
|
||||
field_width = 0;
|
||||
done = FALSE;
|
||||
while (!done)
|
||||
{
|
||||
switch (c = *++p)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
field_width = (field_width * 10) + (c - '0');
|
||||
break;
|
||||
default:
|
||||
/* we've gone one char too far */
|
||||
--p;
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Next check for the width and precision field separator.
|
||||
*/
|
||||
if (/* (c = *++p) */ *++p == '.')
|
||||
{
|
||||
/* precision_used = TRUE; */
|
||||
|
||||
/*
|
||||
* Must get precision field width, if present.
|
||||
*/
|
||||
/* precision_width = 0; */
|
||||
done = FALSE;
|
||||
while (!done)
|
||||
{
|
||||
switch (/* c = uncomment if used below */ *++p)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
#if 0
|
||||
precision_width = (precision_width * 10) +
|
||||
(c - '0');
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
/* we've gone one char too far */
|
||||
--p;
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we've gone one char too far */
|
||||
--p;
|
||||
#if 0
|
||||
precision_used = FALSE;
|
||||
precision_width = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for the length modifier.
|
||||
*/
|
||||
/* length_modifier = 0; */
|
||||
switch (/* c = */ *++p)
|
||||
{
|
||||
case 'h':
|
||||
/* length_modifier |= LENMOD_h; */
|
||||
break;
|
||||
case 'l':
|
||||
/* length_modifier |= LENMOD_l; */
|
||||
break;
|
||||
case 'L':
|
||||
/* length_modifier |= LENMOD_L; */
|
||||
break;
|
||||
default:
|
||||
/* we've gone one char too far */
|
||||
--p;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we're ready to examine the format.
|
||||
*/
|
||||
switch (c = *++p)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
ival = (int)va_arg(ap, int);
|
||||
vlen = printk_mknumstr(vstr,&ival,TRUE,10);
|
||||
vstrp = &vstr[vlen];
|
||||
|
||||
if (ival < 0)
|
||||
{
|
||||
schar = '-';
|
||||
++vlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_FLAG_PLUS(flags_used))
|
||||
{
|
||||
schar = '+';
|
||||
++vlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_FLAG_SPACE(flags_used))
|
||||
{
|
||||
schar = ' ';
|
||||
++vlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
schar = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
dschar = FALSE;
|
||||
|
||||
/*
|
||||
* do the ZERO pad.
|
||||
*/
|
||||
if (IS_FLAG_ZERO(flags_used))
|
||||
{
|
||||
if (schar)
|
||||
printk_putc(schar, &count, info);
|
||||
dschar = TRUE;
|
||||
|
||||
printk_pad_zero (vlen, field_width, &count, info);
|
||||
vlen = field_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IS_FLAG_MINUS(flags_used))
|
||||
{
|
||||
printk_pad_space (vlen, field_width, &count, info);
|
||||
|
||||
if (schar)
|
||||
printk_putc(schar, &count, info);
|
||||
dschar = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* the string was built in reverse order, now display in */
|
||||
/* correct order */
|
||||
if (!dschar && schar)
|
||||
{
|
||||
printk_putc(schar, &count, info);
|
||||
}
|
||||
goto cont_xd;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
uval = (unsigned int)va_arg(ap, unsigned int);
|
||||
vlen = printk_mknumstr(vstr,&uval,FALSE,16);
|
||||
vstrp = &vstr[vlen];
|
||||
|
||||
dschar = FALSE;
|
||||
if (IS_FLAG_ZERO(flags_used))
|
||||
{
|
||||
if (IS_FLAG_POUND(flags_used))
|
||||
{
|
||||
printk_putc('0', &count, info);
|
||||
printk_putc('x', &count, info);
|
||||
/*vlen += 2;*/
|
||||
dschar = TRUE;
|
||||
}
|
||||
printk_pad_zero (vlen, field_width, &count, info);
|
||||
vlen = field_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IS_FLAG_MINUS(flags_used))
|
||||
{
|
||||
if (IS_FLAG_POUND(flags_used))
|
||||
{
|
||||
vlen += 2;
|
||||
}
|
||||
printk_pad_space (vlen, field_width, &count, info);
|
||||
if (IS_FLAG_POUND(flags_used))
|
||||
{
|
||||
printk_putc('0', &count, info);
|
||||
printk_putc('x', &count, info);
|
||||
dschar = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((IS_FLAG_POUND(flags_used)) && !dschar)
|
||||
{
|
||||
printk_putc('0', &count, info);
|
||||
printk_putc('x', &count, info);
|
||||
vlen += 2;
|
||||
}
|
||||
goto cont_xd;
|
||||
|
||||
case 'o':
|
||||
uval = (unsigned int)va_arg(ap, unsigned int);
|
||||
vlen = printk_mknumstr(vstr,&uval,FALSE,8);
|
||||
goto cont_u;
|
||||
case 'b':
|
||||
uval = (unsigned int)va_arg(ap, unsigned int);
|
||||
vlen = printk_mknumstr(vstr,&uval,FALSE,2);
|
||||
goto cont_u;
|
||||
case 'p':
|
||||
uval = (unsigned int)va_arg(ap, void *);
|
||||
vlen = printk_mknumstr(vstr,&uval,FALSE,16);
|
||||
goto cont_u;
|
||||
case 'u':
|
||||
uval = (unsigned int)va_arg(ap, unsigned int);
|
||||
vlen = printk_mknumstr(vstr,&uval,FALSE,10);
|
||||
|
||||
cont_u:
|
||||
vstrp = &vstr[vlen];
|
||||
|
||||
if (IS_FLAG_ZERO(flags_used))
|
||||
{
|
||||
printk_pad_zero (vlen, field_width, &count, info);
|
||||
vlen = field_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IS_FLAG_MINUS(flags_used))
|
||||
{
|
||||
printk_pad_space (vlen, field_width, &count, info);
|
||||
}
|
||||
}
|
||||
|
||||
cont_xd:
|
||||
while (*vstrp)
|
||||
printk_putc(*vstrp--, &count, info);
|
||||
|
||||
if (IS_FLAG_MINUS(flags_used))
|
||||
{
|
||||
printk_pad_space (vlen, field_width, &count, info);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cval = (char)va_arg(ap, unsigned int);
|
||||
printk_putc(cval,&count, info);
|
||||
break;
|
||||
case 's':
|
||||
sval = (char *)va_arg(ap, char *);
|
||||
if (sval)
|
||||
{
|
||||
vlen = strlen(sval);
|
||||
if (!IS_FLAG_MINUS(flags_used))
|
||||
{
|
||||
printk_pad_space (vlen, field_width, &count, info);
|
||||
}
|
||||
while (*sval)
|
||||
printk_putc(*sval++,&count, info);
|
||||
if (IS_FLAG_MINUS(flags_used))
|
||||
{
|
||||
printk_pad_space (vlen, field_width, &count, info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
ivalp = (int *)va_arg(ap, int *);
|
||||
*ivalp = count;
|
||||
break;
|
||||
default:
|
||||
printk_putc(c,&count, info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int
|
||||
printf (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rvalue;
|
||||
PRINTK_INFO info;
|
||||
|
||||
|
||||
info.dest = DEST_CONSOLE;
|
||||
info.func = &out_char;
|
||||
/*
|
||||
* Initialize the pointer to the variable length argument list.
|
||||
*/
|
||||
va_start(ap, fmt);
|
||||
rvalue = printk(&info, fmt, ap);
|
||||
/*
|
||||
* Cleanup the variable length argument list.
|
||||
*/
|
||||
va_end(ap);
|
||||
return rvalue;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int
|
||||
sprintf (char *s, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rvalue = 0;
|
||||
PRINTK_INFO info;
|
||||
|
||||
/*
|
||||
* Initialize the pointer to the variable length argument list.
|
||||
*/
|
||||
if (s != 0)
|
||||
{
|
||||
info.dest = DEST_STRING;
|
||||
info.loc = s;
|
||||
va_start(ap, fmt);
|
||||
rvalue = printk(&info, fmt, ap);
|
||||
*info.loc = '\0';
|
||||
va_end(ap);
|
||||
}
|
||||
return rvalue;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
int puts(const char * s)
|
||||
{
|
||||
printf(s);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,124 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
* @brief Implement a first in, first out linked list.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "queue.h"
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Initialize the specified queue to an empty state
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*/
|
||||
void
|
||||
queue_init(QUEUE *q)
|
||||
{
|
||||
q->head = NULL;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Check for an empty queue
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*
|
||||
* Return Value:
|
||||
* 1 if Queue is empty
|
||||
* 0 otherwise
|
||||
*/
|
||||
int
|
||||
queue_isempty(QUEUE *q)
|
||||
{
|
||||
return (q->head == NULL);
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Add an item to the end of the queue
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
* node New node to add to the queue
|
||||
*/
|
||||
void
|
||||
queue_add(QUEUE *q, QNODE *node)
|
||||
{
|
||||
if (queue_isempty(q))
|
||||
{
|
||||
q->head = q->tail = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
q->tail->next = node;
|
||||
q->tail = node;
|
||||
}
|
||||
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Remove and return first (oldest) entry from the specified queue
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*
|
||||
* Return Value:
|
||||
* Node at head of queue - NULL if queue is empty
|
||||
*/
|
||||
QNODE*
|
||||
queue_remove(QUEUE *q)
|
||||
{
|
||||
QNODE *oldest;
|
||||
|
||||
if (queue_isempty(q))
|
||||
return NULL;
|
||||
|
||||
oldest = q->head;
|
||||
q->head = oldest->next;
|
||||
return oldest;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Peek into the queue and return pointer to first (oldest) entry.
|
||||
* The queue is not modified
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*
|
||||
* Return Value:
|
||||
* Node at head of queue - NULL if queue is empty
|
||||
*/
|
||||
QNODE*
|
||||
queue_peek(QUEUE *q)
|
||||
{
|
||||
return q->head;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Move entire contents of one queue to the other
|
||||
*
|
||||
* Parameters:
|
||||
* src Pointer to source queue
|
||||
* dst Pointer to destination queue
|
||||
*/
|
||||
void
|
||||
queue_move(QUEUE *dst, QUEUE *src)
|
||||
{
|
||||
if (queue_isempty(src))
|
||||
return;
|
||||
|
||||
if (queue_isempty(dst))
|
||||
dst->head = src->head;
|
||||
else
|
||||
dst->tail->next = src->head;
|
||||
|
||||
dst->tail = src->tail;
|
||||
src->head = NULL;
|
||||
return;
|
||||
}
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,52 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief Implement a first in, first out linked list.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Individual queue node
|
||||
*/
|
||||
typedef struct NODE
|
||||
{
|
||||
struct NODE *next;
|
||||
} QNODE;
|
||||
|
||||
/*
|
||||
* Queue Struture - linked list of qentry items
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
QNODE *head;
|
||||
QNODE *tail;
|
||||
} QUEUE;
|
||||
|
||||
/*
|
||||
* Functions provided by queue.c
|
||||
*/
|
||||
void
|
||||
queue_init(QUEUE *);
|
||||
|
||||
int
|
||||
queue_isempty(QUEUE *);
|
||||
|
||||
void
|
||||
queue_add(QUEUE *, QNODE *);
|
||||
|
||||
QNODE*
|
||||
queue_remove(QUEUE *);
|
||||
|
||||
QNODE*
|
||||
queue_peek(QUEUE *);
|
||||
|
||||
void
|
||||
queue_move(QUEUE *, QUEUE *);
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* _QUEUE_H_ */
|
||||
@@ -0,0 +1,77 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief Implement generic NV32 startup code.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#pragma section = ".data"
|
||||
#pragma section = ".data_init"
|
||||
#pragma section = ".bss"
|
||||
#pragma section = "CodeRelocate"
|
||||
#pragma section = "CodeRelocateRam"
|
||||
|
||||
/********************************************************************/
|
||||
void
|
||||
common_startup(void)
|
||||
{
|
||||
// extern char __DATA_ROM[];
|
||||
// extern char __DATA_RAM[];
|
||||
// extern char __DATA_END[];
|
||||
|
||||
/* Declare a counter we'll use in all of the copy loops */
|
||||
uint32 n;
|
||||
|
||||
|
||||
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
|
||||
extern uint32 __VECTOR_TABLE[];
|
||||
extern uint32 __VECTOR_RAM[];
|
||||
|
||||
/* Copy the vector table to RAM */
|
||||
if (__VECTOR_RAM != __VECTOR_TABLE)
|
||||
{
|
||||
for (n = 0; n < 48 ; n++) // for small memory space, excluding flash configuration field
|
||||
|
||||
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
|
||||
}
|
||||
/* Point the VTOR to the new copy of the vector table */
|
||||
write_vtor((uint32)__VECTOR_RAM);
|
||||
|
||||
/* Get the addresses for the .data section (initialized data section) */
|
||||
uint8* data_ram = __section_begin(".data");
|
||||
uint8* data_rom = __section_begin(".data_init");
|
||||
uint8* data_rom_end = __section_end(".data_init");
|
||||
|
||||
/* Copy initialized data from ROM to RAM */
|
||||
n = data_rom_end - data_rom;
|
||||
while (n--)
|
||||
*data_ram++ = *data_rom++;
|
||||
|
||||
|
||||
/* Get the addresses for the .bss section (zero-initialized data) */
|
||||
uint8* bss_start = __section_begin(".bss");
|
||||
uint8* bss_end = __section_end(".bss");
|
||||
|
||||
/* Clear the zero-initialized data section */
|
||||
n = bss_end - bss_start;
|
||||
while(n--)
|
||||
*bss_start++ = 0;
|
||||
|
||||
/* Get addresses for any code sections that need to be copied from ROM to RAM.
|
||||
* The IAR tools have a predefined keyword that can be used to mark individual
|
||||
* functions for execution from RAM. Add "__ramfunc" before the return type in
|
||||
* the function prototype for any routines you need to execute from RAM instead
|
||||
* of ROM. ex: __ramfunc void foo(void);
|
||||
*/
|
||||
uint8* code_relocate_ram = __section_begin("CodeRelocateRam");
|
||||
uint8* code_relocate = __section_begin("CodeRelocate");
|
||||
uint8* code_relocate_end = __section_end("CodeRelocate");
|
||||
|
||||
/* Copy functions from ROM to RAM */
|
||||
n = code_relocate_end - code_relocate;
|
||||
while (n--)
|
||||
*code_relocate_ram++ = *code_relocate++;
|
||||
|
||||
}
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,15 @@
|
||||
/******************************************************************************
|
||||
* @brief Implement generic startup code.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _STARTUP_H_
|
||||
#define _STARTUP_H_
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
void common_startup(void);
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* _STARTUP_H_ */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
** ###################################################################
|
||||
* @brief Device specific configuration file for MKE02Z2 (implementation file)
|
||||
*
|
||||
* Provides a system configuration function and a global variable that contains
|
||||
* the system frequency. It configures the device and initializes the oscillator
|
||||
* (PLL) that is part of the microcontroller device.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "NV32F100.h"
|
||||
|
||||
#define DISABLE_WDOG 1
|
||||
|
||||
#define DEFAULT_SYSTEM_CLOCK 20971520u /* Default System clock value */
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
-- Core clock
|
||||
---------------------------------------------------------------------------- */
|
||||
|
||||
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
-- SystemInit()
|
||||
---------------------------------------------------------------------------- */
|
||||
#define WDOG_TOVAL *((volatile uint16_t *)(&WDOG->TOVALH))
|
||||
#define WDOG_CNT *((volatile uint16_t *)(&WDOG->CNTH))
|
||||
|
||||
void SystemInit (void) {
|
||||
#if (DISABLE_WDOG)
|
||||
/* Disable the WDOG module */
|
||||
WDOG_CNT = 0x20C5;
|
||||
WDOG_CNT = 0x28D9;
|
||||
WDOG_TOVAL = 0xFFFF;
|
||||
//WDOG_WIN = 0; /* NOTE: this will cause HARDFAULT error*/
|
||||
WDOG->WINH = 0xFF;
|
||||
WDOG->WINL = 0xFF;
|
||||
|
||||
WDOG->CS2 = 0x01;
|
||||
WDOG->CS1 = 0x20; /* WDOGA = 1 to allow reconfigure watchdog at any time by executing an unlock sequence */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
-- SystemCoreClockUpdate()
|
||||
---------------------------------------------------------------------------- */
|
||||
|
||||
void SystemCoreClockUpdate (void) {
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* @brief Device specific configuration file for NV32 (header file)
|
||||
*
|
||||
* Provides a system configuration function and a global variable that contains
|
||||
* the system frequency. It configures the device and initializes the oscillator
|
||||
* (PLL) that is part of the microcontroller device.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_NV32_H_
|
||||
#define SYSTEM_NV32_H_ /**< Symbol preventing repeated inclusion */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief System clock frequency (core clock)
|
||||
*
|
||||
* The system clock frequency supplied to the SysTick timer and the processor
|
||||
* core clock. This variable can be used by the user application to setup the
|
||||
* SysTick timer or configure other parameters. It may also be used by debugger to
|
||||
* query the frequency of the debug timer or configure the trace clock speed
|
||||
* SystemCoreClock is initialized with a correct predefined value.
|
||||
*/
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system.
|
||||
*
|
||||
* Typically this function configures the oscillator (PLL) that is part of the
|
||||
* microcontroller device. For systems with variable clock speed it also updates
|
||||
* the variable SystemCoreClock. SystemInit is called from startup_device file.
|
||||
*/
|
||||
void SystemInit (void);
|
||||
|
||||
/**
|
||||
* @brief Updates the SystemCoreClock variable.
|
||||
*
|
||||
* It must be called whenever the core clock is changed during program
|
||||
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
|
||||
* the current core clock.
|
||||
*/
|
||||
void SystemCoreClockUpdate (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if !defined(SYSTEM_NV32_H_) */
|
||||
@@ -0,0 +1,49 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide some type definitions which are not CMSIS style.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __TYPEDEF_H__
|
||||
#define __TYPEDEF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef s8
|
||||
#define s8 char
|
||||
#endif
|
||||
#ifndef u8
|
||||
#define u8 unsigned char
|
||||
#endif
|
||||
#ifndef s16
|
||||
#define s16 short
|
||||
#endif
|
||||
#ifndef u16
|
||||
#define u16 unsigned short
|
||||
#endif
|
||||
#ifndef s32
|
||||
#define s32 long
|
||||
#endif
|
||||
#ifndef u32
|
||||
#define u32 unsigned long
|
||||
#endif
|
||||
#ifndef sint
|
||||
#define sint int
|
||||
#endif
|
||||
#ifndef uint
|
||||
#define uint unsigned int
|
||||
#endif
|
||||
#ifndef s64
|
||||
#define s64 long long
|
||||
#endif
|
||||
#ifndef u64
|
||||
#define u64 unsigned long long
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TYPEDEF_H__ */
|
||||
@@ -0,0 +1,328 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide an interactive user interface.
|
||||
*
|
||||
* The commands, set/show parameters, and prompt are configured at the project level.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "uif.h"
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Global messages -- constant strings
|
||||
*/
|
||||
const char HELPMSG[] =
|
||||
"Enter 'help' for help.\n";
|
||||
|
||||
const char INVARG[] =
|
||||
"Error: Invalid argument: %s\n";
|
||||
|
||||
const char INVALUE[] =
|
||||
"Error: Invalid value: %s\n";
|
||||
|
||||
/*
|
||||
* Strings used by this file only
|
||||
*/
|
||||
static const char INVCMD[] =
|
||||
"Error: No such command: %s\n";
|
||||
|
||||
static const char HELPFORMAT[] =
|
||||
"%8s %-25s %s %s\n";
|
||||
|
||||
static const char SYNTAX[] =
|
||||
"Error: Invalid syntax for: %s\n";
|
||||
|
||||
static const char INVOPT[] =
|
||||
"Error: Invalid set/show option: %s\n";
|
||||
|
||||
static const char OPTFMT[] =
|
||||
"%12s: ";
|
||||
|
||||
static char cmdline1 [UIF_MAX_LINE];
|
||||
static char cmdline2 [UIF_MAX_LINE];
|
||||
|
||||
/********************************************************************/
|
||||
char *
|
||||
get_line (char *line)
|
||||
{
|
||||
int pos;
|
||||
int ch;
|
||||
|
||||
pos = 0;
|
||||
ch = (int)in_char();
|
||||
while ( (ch != 0x0D /* CR */) &&
|
||||
(ch != 0x0A /* LF/NL */) &&
|
||||
(pos < UIF_MAX_LINE))
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 0x08: /* Backspace */
|
||||
case 0x7F: /* Delete */
|
||||
if (pos > 0)
|
||||
{
|
||||
pos -= 1;
|
||||
out_char(0x08); /* backspace */
|
||||
out_char(' ');
|
||||
out_char(0x08); /* backspace */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ((pos+1) < UIF_MAX_LINE)
|
||||
{
|
||||
if ((ch > 0x1f) && (ch < 0x80))
|
||||
{
|
||||
line[pos++] = (char)ch;
|
||||
out_char((char)ch);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ch = (int)in_char();
|
||||
}
|
||||
line[pos] = '\0';
|
||||
out_char(0x0D); /* CR */
|
||||
out_char(0x0A); /* LF */
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int
|
||||
make_argv (char *cmdline, char *argv[])
|
||||
{
|
||||
int argc, i, in_text;
|
||||
|
||||
/*
|
||||
* Break cmdline into strings and argv
|
||||
* It is permissible for argv to be NULL, in which case
|
||||
* the purpose of this routine becomes to count args
|
||||
*/
|
||||
argc = 0;
|
||||
i = 0;
|
||||
in_text = FALSE;
|
||||
while (cmdline[i] != '\0') /* getline() must place 0x00 on end */
|
||||
{
|
||||
if (((cmdline[i] == ' ') ||
|
||||
(cmdline[i] == '\t')) )
|
||||
{
|
||||
if (in_text)
|
||||
{
|
||||
/* end of command line argument */
|
||||
cmdline[i] = '\0';
|
||||
in_text = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* still looking for next argument */
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* got non-whitespace character */
|
||||
if (in_text)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
/* start of an argument */
|
||||
in_text = TRUE;
|
||||
if (argc < UIF_MAX_ARGS)
|
||||
{
|
||||
if (argv != NULL)
|
||||
argv[argc] = &cmdline[i];
|
||||
argc++;
|
||||
}
|
||||
else
|
||||
/*return argc;*/
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
i++; /* proceed to next character */
|
||||
}
|
||||
if (argv != NULL)
|
||||
argv[argc] = NULL;
|
||||
return argc;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
void
|
||||
run_cmd (void)
|
||||
{
|
||||
/*
|
||||
* Global array of pointers to emulate C argc,argv interface
|
||||
*/
|
||||
int argc;
|
||||
char *argv[UIF_MAX_ARGS + 1]; /* one extra for null terminator */
|
||||
|
||||
get_line(cmdline1);
|
||||
|
||||
if (!(argc = make_argv(cmdline1,argv)))
|
||||
{
|
||||
/* no command entered, just a blank line */
|
||||
strcpy(cmdline1,cmdline2);
|
||||
argc = make_argv(cmdline1,argv);
|
||||
}
|
||||
cmdline2[0] = '\0';
|
||||
|
||||
if (argc)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < UIF_NUM_CMD; i++)
|
||||
{
|
||||
if (strcasecmp(UIF_CMDTAB[i].cmd,argv[0]) == 0)
|
||||
{
|
||||
if (((argc-1) >= UIF_CMDTAB[i].min_args) &&
|
||||
((argc-1) <= UIF_CMDTAB[i].max_args))
|
||||
{
|
||||
if (UIF_CMDTAB[i].flags & UIF_CMD_FLAG_REPEAT)
|
||||
{
|
||||
strcpy(cmdline2,argv[0]);
|
||||
}
|
||||
UIF_CMDTAB[i].func(argc,argv);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(SYNTAX,argv[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(INVCMD,argv[0]);
|
||||
printf(HELPMSG);
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
uint32
|
||||
get_value (char *s, int *success, int base)
|
||||
{
|
||||
uint32 value;
|
||||
char *p;
|
||||
|
||||
value = strtoul(s,&p,base);
|
||||
if ((value == 0) && (p == s))
|
||||
{
|
||||
*success = FALSE;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*success = TRUE;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
uif_cmd_help (int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf("\n");
|
||||
for (index = 0; index < UIF_NUM_CMD; index++)
|
||||
{
|
||||
printf(HELPFORMAT,
|
||||
UIF_CMDTAB[index].cmd,
|
||||
UIF_CMDTAB[index].description,
|
||||
UIF_CMDTAB[index].cmd,
|
||||
UIF_CMDTAB[index].syntax);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
uif_cmd_set (int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
printf("\n");
|
||||
if (argc == 1)
|
||||
{
|
||||
printf("Valid 'set' options:\n");
|
||||
for (index = 0; index < UIF_NUM_SETCMD; ++index)
|
||||
{
|
||||
printf(OPTFMT,UIF_SETCMDTAB[index].option);
|
||||
printf("%s\n",UIF_SETCMDTAB[index].syntax);
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("Error: Invalid argument list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (index = 0; index < UIF_NUM_SETCMD; index++)
|
||||
{
|
||||
if (strcasecmp(UIF_SETCMDTAB[index].option,argv[1]) == 0)
|
||||
{
|
||||
if (((argc-1-1) >= UIF_SETCMDTAB[index].min_args) &&
|
||||
((argc-1-1) <= UIF_SETCMDTAB[index].max_args))
|
||||
{
|
||||
UIF_SETCMDTAB[index].func(argc,argv);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(INVARG,argv[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(INVOPT,argv[1]);
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
void
|
||||
uif_cmd_show (int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
printf("\n");
|
||||
if (argc == 1)
|
||||
{
|
||||
/*
|
||||
* Show all Option settings
|
||||
*/
|
||||
argc = 2;
|
||||
argv[2] = NULL;
|
||||
for (index = 0; index < UIF_NUM_SETCMD; index++)
|
||||
{
|
||||
printf(OPTFMT,UIF_SETCMDTAB[index].option);
|
||||
UIF_SETCMDTAB[index].func(argc,argv);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (index = 0; index < UIF_NUM_SETCMD; index++)
|
||||
{
|
||||
if (strcasecmp(UIF_SETCMDTAB[index].option,argv[1]) == 0)
|
||||
{
|
||||
if (((argc-1-1) >= UIF_SETCMDTAB[index].min_args) &&
|
||||
((argc-1-1) <= UIF_SETCMDTAB[index].max_args))
|
||||
{
|
||||
printf(OPTFMT,UIF_SETCMDTAB[index].option);
|
||||
UIF_SETCMDTAB[index].func(argc,argv);
|
||||
printf("\n\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(INVARG,argv[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(INVOPT,argv[1]);
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,123 @@
|
||||
/********************************************************************************
|
||||
* @brief provide an interactive user interface.
|
||||
*
|
||||
* The commands, set/show parameters, and prompt are configured at the project level.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _UIF_H_
|
||||
#define _UIF_H_
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
char *
|
||||
get_line (char *);
|
||||
|
||||
uint32
|
||||
get_value (char *, int *, int);
|
||||
|
||||
void
|
||||
run_cmd (void);
|
||||
|
||||
int
|
||||
make_argv (char *, char **);
|
||||
|
||||
void
|
||||
uif_cmd_help (int, char **);
|
||||
|
||||
void
|
||||
uif_cmd_set (int, char **);
|
||||
|
||||
void
|
||||
uif_cmd_show (int, char **);
|
||||
|
||||
/*
|
||||
* Maximum command line arguments
|
||||
*/
|
||||
#define UIF_MAX_ARGS 10
|
||||
|
||||
/*
|
||||
* Maximum length of the command line
|
||||
*/
|
||||
#define UIF_MAX_LINE 80
|
||||
|
||||
/*
|
||||
* The command table entry data structure
|
||||
*/
|
||||
typedef const struct
|
||||
{
|
||||
char * cmd; /* command name user types, ie. GO */
|
||||
int min_args; /* min num of args command accepts */
|
||||
int max_args; /* max num of args command accepts */
|
||||
int flags; /* command flags (e.g. repeat) */
|
||||
void (*func)(int, char **); /* actual function to call */
|
||||
char * description; /* brief description of command */
|
||||
char * syntax; /* syntax of command */
|
||||
} UIF_CMD;
|
||||
|
||||
/*
|
||||
* Prototype and macro for size of the command table
|
||||
*/
|
||||
extern UIF_CMD UIF_CMDTAB[];
|
||||
extern const int UIF_NUM_CMD;
|
||||
#define UIF_CMDTAB_SIZE (sizeof(UIF_CMDTAB)/sizeof(UIF_CMD))
|
||||
|
||||
#define UIF_CMD_FLAG_REPEAT 0x1
|
||||
|
||||
/*
|
||||
* Macros for User InterFace command table entries
|
||||
*/
|
||||
#ifndef UIF_CMD_HELP
|
||||
#define UIF_CMD_HELP \
|
||||
{"help",0,1,0,uif_cmd_help,"Help","<cmd>"},
|
||||
#endif
|
||||
|
||||
#ifndef UIF_CMD_SET
|
||||
#define UIF_CMD_SET \
|
||||
{"set",0,2,0,uif_cmd_set,"Set Config","<option value>"},
|
||||
#endif
|
||||
|
||||
#ifndef UIF_CMD_SHOW
|
||||
#define UIF_CMD_SHOW \
|
||||
{"show",0,1,0,uif_cmd_show,"Show Config","<option>"},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro to include all standard user interface commands
|
||||
*/
|
||||
#define UIF_CMDS_ALL \
|
||||
UIF_CMD_HELP \
|
||||
UIF_CMD_SET \
|
||||
UIF_CMD_SHOW
|
||||
|
||||
/*
|
||||
* The set/show table entry data structure
|
||||
*/
|
||||
typedef const struct
|
||||
{
|
||||
char * option;
|
||||
int min_args;
|
||||
int max_args;
|
||||
void (*func)(int, char **);
|
||||
char * syntax;
|
||||
} UIF_SETCMD;
|
||||
|
||||
/*
|
||||
* Prototype and macro for size of the table
|
||||
*/
|
||||
extern UIF_SETCMD UIF_SETCMDTAB[];
|
||||
extern const int UIF_NUM_SETCMD;
|
||||
#define UIF_SETCMDTAB_SIZE (sizeof(UIF_SETCMDTAB)/sizeof(UIF_SETCMD))
|
||||
|
||||
/*
|
||||
* Strings defined in uif.c that may be useful to external functions
|
||||
*/
|
||||
extern const char HELPMSG[];
|
||||
extern const char INVARG[];
|
||||
extern const char INVALUE[];
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* _UIF_H_ */
|
||||
@@ -0,0 +1,77 @@
|
||||
/******************************************************************************
|
||||
* @brief provide generic high-level routines for ARM Cortex M0/M0+ processors.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/*
|
||||
* Configures the ARM system control register for STOP (deep sleep) mode
|
||||
* and then executes the WFI instruction to enter the mode.
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
*
|
||||
* Note: Might want to change this later to allow for passing in a parameter
|
||||
* to optionally set the sleep on exit bit.
|
||||
*/
|
||||
|
||||
void stop (void)
|
||||
{
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* WFI instruction will start entry into STOP mode */
|
||||
#ifndef KEIL
|
||||
// If not using KEIL's uVision use the standard assembly command
|
||||
asm("WFI");
|
||||
#else
|
||||
// If using KEIL's uVision, use the CMSIS intrinsic
|
||||
__wfi();
|
||||
#endif
|
||||
}
|
||||
/***********************************************************************/
|
||||
/*
|
||||
* Configures the ARM system control register for WAIT (sleep) mode
|
||||
* and then executes the WFI instruction to enter the mode.
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
*
|
||||
* Note: Might want to change this later to allow for passing in a parameter
|
||||
* to optionally set the sleep on exit bit.
|
||||
*/
|
||||
|
||||
void wait (void)
|
||||
{
|
||||
/* Clear the SLEEPDEEP bit to make sure we go into WAIT (sleep) mode instead
|
||||
* of deep sleep.
|
||||
*/
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* WFI instruction will start entry into WAIT mode */
|
||||
#ifndef KEIL
|
||||
// If not using KEIL's uVision use the standard assembly command
|
||||
asm("WFI");
|
||||
#else
|
||||
// If using KEIL's uVision, use the CMSIS intrinsic
|
||||
__wfi();
|
||||
#endif
|
||||
}
|
||||
/***********************************************************************/
|
||||
/*
|
||||
* Change the value of the vector table offset register to the specified value.
|
||||
*
|
||||
* Parameters:
|
||||
* vtor new value to write to the VTOR
|
||||
*/
|
||||
|
||||
void write_vtor (int vtor)
|
||||
{
|
||||
/* Write the VTOR with the new value */
|
||||
SCB->VTOR = vtor;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide generic high-level routines for ARM Cortex M0/M0+ processors.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _CPU_ARM_CM0_H
|
||||
#define _CPU_ARM_CM0_H
|
||||
|
||||
/*ARM Cortex M0 implementation for interrupt priority shift*/
|
||||
#define ARM_INTERRUPT_LEVEL_BITS 2
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/*!< Macro to enable all interrupts. */
|
||||
#ifndef KEIL
|
||||
#define EnableInterrupts __set_PRIMASK(0) //Modify
|
||||
#else
|
||||
#define EnableInterrupts __set_PRIMASK(0)
|
||||
#endif
|
||||
|
||||
/*!< Macro to disable all interrupts. */
|
||||
#ifndef KEIL
|
||||
#define DisableInterrupts __set_PRIMASK(1)
|
||||
#else
|
||||
#define DisableInterrupts __set_PRIMASK(1)
|
||||
#endif
|
||||
|
||||
#define disable_irq(irq) NVIC_DisableIRQ(irq)
|
||||
#define enable_irq(irq) NVIC_EnableIRQ(irq)
|
||||
#define set_irq_priority(irq, prio) NVIC_SetPriority(irq, prio)
|
||||
/***********************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* Misc. Defines
|
||||
*/
|
||||
#ifdef FALSE
|
||||
#undef FALSE
|
||||
#endif
|
||||
#define FALSE (0)
|
||||
|
||||
#ifdef TRUE
|
||||
#undef TRUE
|
||||
#endif
|
||||
#define TRUE (1)
|
||||
|
||||
#ifdef NULL
|
||||
#undef NULL
|
||||
#endif
|
||||
#define NULL (0)
|
||||
|
||||
#ifdef ON
|
||||
#undef ON
|
||||
#endif
|
||||
#define ON (1)
|
||||
|
||||
#ifdef OFF
|
||||
#undef OFF
|
||||
#endif
|
||||
#define OFF (0)
|
||||
|
||||
#undef ENABLE
|
||||
#define ENABLE (1)
|
||||
|
||||
#undef DISABLE
|
||||
#define DISABLE (0)
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/*
|
||||
* The basic data types
|
||||
*/
|
||||
typedef unsigned char uint8; /* 8 bits */
|
||||
typedef unsigned short int uint16; /* 16 bits */
|
||||
typedef unsigned long int uint32; /* 32 bits */
|
||||
|
||||
typedef char int8; /* 8 bits */
|
||||
typedef short int int16; /* 16 bits */
|
||||
typedef int int32; /* 32 bits */
|
||||
|
||||
typedef volatile int8 vint8; /* 8 bits */
|
||||
typedef volatile int16 vint16; /* 16 bits */
|
||||
typedef volatile int32 vint32; /* 32 bits */
|
||||
|
||||
typedef volatile uint8 vuint8; /* 8 bits */
|
||||
typedef volatile uint16 vuint16; /* 16 bits */
|
||||
typedef volatile uint32 vuint32; /* 32 bits */
|
||||
|
||||
// function prototype for main function
|
||||
int main(void);
|
||||
/***********************************************************************/
|
||||
// function prototypes for arm_cm0.c
|
||||
void stop (void);
|
||||
void wait (void);
|
||||
void write_vtor (int);
|
||||
|
||||
/***********************************************************************/
|
||||
#endif /* _CPU_ARM_CM4_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Note: This file is recreated by the project wizard whenever the MCU is
|
||||
* changed and should not be edited by hand
|
||||
*/
|
||||
|
||||
/* Include the derivative-specific header file */
|
||||
#include <NV32.h>
|
||||
#include "arm_cm0.h"
|
||||
@@ -0,0 +1,65 @@
|
||||
/******************************************************************************
|
||||
* @brief provide high-level startup routines for NV32Fxx.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "start.h"
|
||||
#include "common.h"
|
||||
#include "wdog.h"
|
||||
#include "sysinit.h"
|
||||
|
||||
void start(void);
|
||||
void SystemInit( void );
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Start
|
||||
* \return None
|
||||
*
|
||||
* This function calls all of the needed starup routines and then
|
||||
* branches to the main process.
|
||||
*/
|
||||
void start(void)
|
||||
{
|
||||
|
||||
/* Disable the watchdog ETMer but enable update */
|
||||
WDOG_DisableWDOGEnableUpdate();
|
||||
|
||||
#ifndef __GNUC__
|
||||
#ifndef KEIL
|
||||
|
||||
/* Copy any vector or data sections that need to be in RAM */
|
||||
common_startup();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Jump to main process */
|
||||
main();
|
||||
|
||||
/* No actions to perform after this so wait forever */
|
||||
while(1);
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief flash SystemInit
|
||||
* \return None
|
||||
*
|
||||
* this is a system initialization function which dediu16Cated in Keil
|
||||
* others complier don't use it.
|
||||
* it is similar to start function
|
||||
*/
|
||||
void SystemInit( void )
|
||||
{
|
||||
#if !defined(ENABLE_WDOG)
|
||||
/* Disable the watchdog ETMer */
|
||||
WDOG_Disable();
|
||||
#else
|
||||
/* Disable the watchdog ETMer but enable update */
|
||||
WDOG_DisableWDOGEnableUpdate();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/******************************************************************************
|
||||
* @brief provide high-level startup routines for NV32Fxx.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/* Function prototypes */
|
||||
void start(void);
|
||||
@@ -0,0 +1,88 @@
|
||||
.syntax unified
|
||||
.arch armv6-m
|
||||
.fpu softvfp
|
||||
.thumb
|
||||
|
||||
.global g_pfnVectors
|
||||
.global Default_Handler
|
||||
|
||||
/* start address for the initialization values of the .data section.
|
||||
defined in linker script */
|
||||
.word _sidata
|
||||
/* start address for the .data section. defined in linker script */
|
||||
.word _sdata
|
||||
/* end address for the .data section. defined in linker script */
|
||||
.word _edata
|
||||
/* start address for the .bss section. defined in linker script */
|
||||
.word _sbss
|
||||
/* end address for the .bss section. defined in linker script */
|
||||
.word _ebss
|
||||
|
||||
|
||||
|
||||
|
||||
.section .text.Reset_Handler
|
||||
.weak Reset_Handler
|
||||
.type Reset_Handler, %function
|
||||
Reset_Handler:
|
||||
ldr r0, =_estack
|
||||
mov sp, r0 /* set stack pointer */
|
||||
|
||||
/* Copy the data segment initializers from flash to SRAM */
|
||||
movs r1, #0
|
||||
b LoopCopyDataInit
|
||||
|
||||
CopyDataInit:
|
||||
ldr r3, =_sidata
|
||||
ldr r3, [r3, r1]
|
||||
str r3, [r0, r1]
|
||||
adds r1, r1, #4
|
||||
|
||||
LoopCopyDataInit:
|
||||
ldr r0, =_sdata
|
||||
ldr r3, =_edata
|
||||
adds r2, r0, r1
|
||||
cmp r2, r3
|
||||
bcc CopyDataInit
|
||||
ldr r2, =_sbss
|
||||
b LoopFillZerobss
|
||||
/* Zero fill the bss segment. */
|
||||
FillZerobss:
|
||||
movs r3, #0
|
||||
str r3, [r2]
|
||||
adds r2, r2, #4
|
||||
|
||||
|
||||
LoopFillZerobss:
|
||||
ldr r3, = _ebss
|
||||
cmp r2, r3
|
||||
bcc FillZerobss
|
||||
|
||||
/* Call the clock system intitialization function.*/
|
||||
bl SystemInit
|
||||
|
||||
/* Call the application's entry point.*/
|
||||
bl main
|
||||
|
||||
LoopForever:
|
||||
b LoopForever
|
||||
|
||||
|
||||
.size Reset_Handler, .-Reset_Handler
|
||||
|
||||
/**
|
||||
* @brief This is the code that gets called when the processor receives an
|
||||
* unexpected interrupt. This simply enters an infinite loop, preserving
|
||||
* the system state for examination by a debugger.
|
||||
*
|
||||
* @param None
|
||||
* @retval : None
|
||||
*/
|
||||
.section .text.Default_Handler,"ax",%progbits
|
||||
Default_Handler:
|
||||
Infinite_Loop:
|
||||
b Infinite_Loop
|
||||
.size Default_Handler, .-Default_Handler
|
||||
|
||||
/* Vectors and flash protection config in vectors.c */
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
;/*****************************************************************************
|
||||
; * @file: startup_NV32.s
|
||||
; * @purpose: CMSIS Cortex-M0plus Core Device Startup File for the
|
||||
; * NV32F100
|
||||
;*
|
||||
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
|
||||
; *
|
||||
; *****************************************************************************/
|
||||
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Stack_Size EQU 0x00000400
|
||||
|
||||
AREA STACK, NOINIT, READWRITE, ALIGN=3
|
||||
Stack_Mem SPACE Stack_Size
|
||||
__initial_sp
|
||||
|
||||
|
||||
; <h> Heap Configuration
|
||||
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Heap_Size EQU 0x00000000
|
||||
|
||||
AREA HEAP, NOINIT, READWRITE, ALIGN=3
|
||||
__heap_base
|
||||
Heap_Mem SPACE Heap_Size
|
||||
__heap_limit
|
||||
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
|
||||
; Vector Table Mapped to Address 0 at Reset
|
||||
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
EXPORT __Vectors_End
|
||||
EXPORT __Vectors_Size
|
||||
|
||||
__Vectors DCD __initial_sp ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
DCD NMI_Handler ; NMI Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler ; SVCall Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler ; PendSV Handler
|
||||
DCD SysTick_Handler ; SysTick Handler
|
||||
|
||||
; External Interrupts
|
||||
DCD Reserved16_IRQHandler ; Reserved interrupt 16
|
||||
DCD Reserved17_IRQHandler ; Reserved interrupt 17
|
||||
DCD Reserved18_IRQHandler ; Reserved interrupt 18
|
||||
DCD Reserved19_IRQHandler ; Reserved interrupt 19
|
||||
DCD Reserved20_IRQHandler ; Reserved interrupt 20
|
||||
DCD ETMRH_IRQHandler ; ETMRH command complete/read collision interrupt
|
||||
DCD LVD_LVW_IRQHandler ; Low Voltage Detect, Low Voltage Warning
|
||||
DCD IRQ_IRQHandler ; External interrupt
|
||||
DCD I2C0_IRQHandler ; I2C0 interrupt
|
||||
DCD Reserved25_IRQHandler ; Reserved interrupt 25
|
||||
DCD SPI0_IRQHandler ; SPI0 interrupt
|
||||
DCD SPI1_IRQHandler ; SPI1 interrupt
|
||||
DCD UART0_IRQHandler ; UART0 status/error interrupt
|
||||
DCD UART1_IRQHandler ; UART1 status/error interrupt
|
||||
DCD UART2_IRQHandler ; UART2 status/error interrupt
|
||||
DCD ADC0_IRQHandler ; ADC0 interrupt
|
||||
DCD ACMP0_IRQHandler ; ACMP0 interrupt
|
||||
DCD ETM0_IRQHandler ; ETM0 Single interrupt vector for all sources
|
||||
DCD ETM1_IRQHandler ; ETM1 Single interrupt vector for all sources
|
||||
DCD ETM2_IRQHandler ; ETM2 Single interrupt vector for all sources
|
||||
DCD RTC_IRQHandler ; RTC overflow
|
||||
DCD ACMP1_IRQHandler ; ACMP1 interrupt
|
||||
DCD PIT_CH0_IRQHandler ; PIT CH0 overflow
|
||||
DCD PIT_CH1_IRQHandler ; PIT CH1 overflow
|
||||
DCD KBI0_IRQHandler ; Keyboard interrupt 0
|
||||
DCD KBI1_IRQHandler ; Keyboard interrupt 1
|
||||
DCD Reserved42_IRQHandler ; Reserved interrupt 42
|
||||
DCD ICS_IRQHandler ; MCG interrupt
|
||||
DCD Watchdog_IRQHandler ; WDOG Interrupt
|
||||
DCD Reserved45_IRQHandler ; Reserved interrupt 45
|
||||
DCD Reserved46_IRQHandler ; Reserved interrupt 46
|
||||
DCD Reserved47_IRQHandler ; Reserved interrupt 47
|
||||
__Vectors_End
|
||||
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
; <h> Flash Configuration
|
||||
; <i> 16-byte flash configuration field that stores default protection settings (loaded on reset)
|
||||
; <i> and security information that allows the MCU to restrict acces to the FTFL module.
|
||||
; <h> Backdoor Comparison Key
|
||||
; <o0> Backdoor Key 0 <0x0-0xFF:2>
|
||||
; <o1> Backdoor Key 1 <0x0-0xFF:2>
|
||||
; <o2> Backdoor Key 2 <0x0-0xFF:2>
|
||||
; <o3> Backdoor Key 3 <0x0-0xFF:2>
|
||||
; <o4> Backdoor Key 4 <0x0-0xFF:2>
|
||||
; <o5> Backdoor Key 5 <0x0-0xFF:2>
|
||||
; <o6> Backdoor Key 6 <0x0-0xFF:2>
|
||||
; <o7> Backdoor Key 7 <0x0-0xFF:2>
|
||||
BackDoorK0 EQU 0xFF
|
||||
BackDoorK1 EQU 0xFF
|
||||
BackDoorK2 EQU 0xFF
|
||||
BackDoorK3 EQU 0xFF
|
||||
BackDoorK4 EQU 0xFF
|
||||
BackDoorK5 EQU 0xFF
|
||||
BackDoorK6 EQU 0xFF
|
||||
BackDoorK7 EQU 0xFF
|
||||
; </h>
|
||||
; <h> EEPROM Protection Register (EEPROT)
|
||||
; <i> The DFPROT register defines which D-Flash sectors are protected against program and erase operations.
|
||||
; <o.7> DPOPEN
|
||||
; <0=> Enables EEPROM memory protection
|
||||
; <1=> Disables EEPROM memory protection
|
||||
; <o.0..2> DPS
|
||||
; <0=> Flash address range: 0x00_0000 - 0x00_001F; protected size: 32 bytes
|
||||
; <1=> Flash address range: 0x00_0000 - 0x00_003F; protected size: 64 bytes
|
||||
; <2=> Flash address range: 0x00_0000 - 0x00_005F; protected size: 96 bytes
|
||||
; <3=> Flash address range: 0x00_0000 - 0x00_007F; protected size: 128 bytes
|
||||
; <4=> Flash address range: 0x00_0000 - 0x00_009F; protected size: 160 bytes
|
||||
; <5=> Flash address range: 0x00_0000 - 0x00_00BF; protected size: 192 bytes
|
||||
; <6=> Flash address range: 0x00_0000 - 0x00_00DF; protected size: 224 bytes
|
||||
; <7=> Flash address range: 0x00_0000 - 0x00_00FF; protected size: 256 bytes
|
||||
EEPROT EQU 0xFF
|
||||
; </h>
|
||||
; <h> FPROT
|
||||
; <i> P-Flash Protection Register
|
||||
; <o.7> FPOPEN
|
||||
; <0=> FPHDIS and FPLDIS bits define unprotected address ranges as specified by the corresponding FPHS and FPLS bits FPROT1.1
|
||||
; <1=> FPHDIS and FPLDIS bits enable protection for the address range specified by the corresponding FPHS and FPLS bits
|
||||
; <o.5> FPHDIS
|
||||
; <0=> Protection/Unprotection enabled
|
||||
; <1=> Protection/Unprotection disabled
|
||||
; <o.3..4> FPHS
|
||||
; <0=> Address range: 0x00_7C00-0x00_7FFF; protected size: 1 KB
|
||||
; <1=> Address range: 0x00_7800-0x00_7FFF; protected size: 2 KB
|
||||
; <2=> Address range: 0x00_7000-0x00_7FFF; protected size: 4 KB
|
||||
; <3=> Address range: 0x00_6000-0x00_7FFF; protected size: 8 KB
|
||||
; <o.5> FPLDIS
|
||||
; <0=> Protection/Unprotection enabled
|
||||
; <1=> Protection/Unprotection disabled
|
||||
; <o.3..4> FPLS
|
||||
; <0=> Address range: 0x00_0000-0x00_07FF; protected size: 2 KB
|
||||
; <1=> Address range: 0x00_0000-0x00_0FFF; protected size: 4 KB
|
||||
; <2=> Address range: 0x00_0000-0x00_1FFF; protected size: 8 KB
|
||||
; <3=> Address range: 0x00_0000-0x00_3FFF; protected size: 16 KB
|
||||
FPROT EQU 0xFF
|
||||
; </h>
|
||||
; </h>
|
||||
; <h> Flash security byte (FSEC)
|
||||
; <i> WARNING: If SEC field is configured as "MCU security status is secure" and MEEN field is configured as "Mass erase is disabled",
|
||||
; <i> MCU's security status cannot be set back to unsecure state since Mass erase via the debugger is blocked !!!
|
||||
; <o.0..1> SEC
|
||||
; <2=> MCU security status is unsecure
|
||||
; <3=> MCU security status is secure
|
||||
; <i> Flash Security
|
||||
; <i> This bits define the security state of the MCU.
|
||||
; <o.6..7> KEYEN
|
||||
; <2=> Backdoor key access enabled
|
||||
; <3=> Backdoor key access disabled
|
||||
; <i> Backdoor key Security Enable
|
||||
; <i> These bits enable and disable backdoor key access to the FTFL module.
|
||||
FSEC EQU 0xFE
|
||||
; </h>
|
||||
; <h> Flash Option Register (FOPT)
|
||||
FOPT EQU 0xFE
|
||||
; </h>
|
||||
IF :LNOT::DEF:RAM_TARGET
|
||||
AREA |.ARM.__at_0x400|, CODE, READONLY
|
||||
DCB BackDoorK0, BackDoorK1, BackDoorK2, BackDoorK3
|
||||
DCB BackDoorK4, BackDoorK5, BackDoorK6, BackDoorK7
|
||||
DCB 0xFF, 0xFF, 0xFF, 0xFF
|
||||
DCB EEPROT, FPROT, FSEC, FOPT ;Modified by ARM. DCB FPROT, EEPROT, FOPT, FSEC
|
||||
ENDIF
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
|
||||
; Reset Handler
|
||||
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
|
||||
; Dummy Exception Handlers (infinite loops which can be modified)
|
||||
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
HardFault_Handler\
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
MemManage_Handler\
|
||||
PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
BusFault_Handler\
|
||||
PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
UsageFault_Handler\
|
||||
PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
DebugMon_Handler\
|
||||
PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
PendSV_Handler PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SysTick_Handler PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
EXPORT Reserved16_IRQHandler [WEAK]
|
||||
EXPORT Reserved17_IRQHandler [WEAK]
|
||||
EXPORT Reserved18_IRQHandler [WEAK]
|
||||
EXPORT Reserved19_IRQHandler [WEAK]
|
||||
EXPORT Reserved20_IRQHandler [WEAK]
|
||||
EXPORT ETMRH_IRQHandler [WEAK]
|
||||
EXPORT LVD_LVW_IRQHandler [WEAK]
|
||||
EXPORT IRQ_IRQHandler [WEAK]
|
||||
EXPORT I2C0_IRQHandler [WEAK]
|
||||
EXPORT Reserved25_IRQHandler [WEAK]
|
||||
EXPORT SPI0_IRQHandler [WEAK]
|
||||
EXPORT SPI1_IRQHandler [WEAK]
|
||||
EXPORT UART0_IRQHandler [WEAK]
|
||||
EXPORT UART1_IRQHandler [WEAK]
|
||||
EXPORT UART2_IRQHandler [WEAK]
|
||||
EXPORT ADC0_IRQHandler [WEAK]
|
||||
EXPORT ACMP0_IRQHandler [WEAK]
|
||||
EXPORT ETM0_IRQHandler [WEAK]
|
||||
EXPORT ETM1_IRQHandler [WEAK]
|
||||
EXPORT ETM2_IRQHandler [WEAK]
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
EXPORT ACMP1_IRQHandler [WEAK]
|
||||
EXPORT PIT_CH0_IRQHandler [WEAK]
|
||||
EXPORT PIT_CH1_IRQHandler [WEAK]
|
||||
EXPORT KBI0_IRQHandler [WEAK]
|
||||
EXPORT KBI1_IRQHandler [WEAK]
|
||||
EXPORT Reserved42_IRQHandler [WEAK]
|
||||
EXPORT ICS_IRQHandler [WEAK]
|
||||
EXPORT Watchdog_IRQHandler [WEAK]
|
||||
EXPORT Reserved45_IRQHandler [WEAK]
|
||||
EXPORT Reserved46_IRQHandler [WEAK]
|
||||
EXPORT Reserved47_IRQHandler [WEAK]
|
||||
EXPORT DefaultISR [WEAK]
|
||||
|
||||
Reserved16_IRQHandler
|
||||
Reserved17_IRQHandler
|
||||
Reserved18_IRQHandler
|
||||
Reserved19_IRQHandler
|
||||
Reserved20_IRQHandler
|
||||
ETMRH_IRQHandler
|
||||
LVD_LVW_IRQHandler
|
||||
IRQ_IRQHandler
|
||||
I2C0_IRQHandler
|
||||
Reserved25_IRQHandler
|
||||
SPI0_IRQHandler
|
||||
SPI1_IRQHandler
|
||||
UART0_IRQHandler
|
||||
UART1_IRQHandler
|
||||
UART2_IRQHandler
|
||||
ADC0_IRQHandler
|
||||
ACMP0_IRQHandler
|
||||
ETM0_IRQHandler
|
||||
ETM1_IRQHandler
|
||||
ETM2_IRQHandler
|
||||
RTC_IRQHandler
|
||||
ACMP1_IRQHandler
|
||||
PIT_CH0_IRQHandler
|
||||
PIT_CH1_IRQHandler
|
||||
KBI0_IRQHandler
|
||||
KBI1_IRQHandler
|
||||
Reserved42_IRQHandler
|
||||
ICS_IRQHandler
|
||||
Watchdog_IRQHandler
|
||||
Reserved45_IRQHandler
|
||||
Reserved46_IRQHandler
|
||||
Reserved47_IRQHandler
|
||||
DefaultISR
|
||||
|
||||
B .
|
||||
|
||||
ENDP
|
||||
|
||||
|
||||
ALIGN
|
||||
|
||||
|
||||
; User Initial Stack & Heap
|
||||
|
||||
IF :DEF:__MICROLIB
|
||||
|
||||
EXPORT __initial_sp
|
||||
EXPORT __heap_base
|
||||
EXPORT __heap_limit
|
||||
|
||||
ELSE
|
||||
|
||||
IMPORT __use_two_region_memory
|
||||
EXPORT __user_initial_stackheap
|
||||
__user_initial_stackheap
|
||||
|
||||
LDR R0, = Heap_Mem
|
||||
LDR R1, =(Stack_Mem + Stack_Size)
|
||||
LDR R2, = (Heap_Mem + Heap_Size)
|
||||
LDR R3, = Stack_Mem
|
||||
BX LR
|
||||
|
||||
ALIGN
|
||||
|
||||
ENDIF
|
||||
|
||||
|
||||
END
|
||||
@@ -0,0 +1,257 @@
|
||||
/*****************************************************************************
|
||||
* @brief provide system init routine/configuration for NV32Fxx.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "sysinit.h"
|
||||
#include "sim.h"
|
||||
#include "uart.h"
|
||||
#include "ics.h"
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
uint16_t global_pass_count = 0;
|
||||
uint16_t global_fail_count = 0;
|
||||
|
||||
|
||||
void print_sys_log(void);
|
||||
void UART_InitPrint(void);
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: sysinit
|
||||
*
|
||||
* @brief initalize system including SIM, ICS, UART, etc
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
void sysinit (void)
|
||||
{
|
||||
SIM_ConfigType sSIMConfig = {{0},0};
|
||||
ICS_ConfigType sICSConfig = {0};
|
||||
|
||||
/* initialize the Pass/Fail counts to 0 */
|
||||
global_pass_count = 0;
|
||||
global_fail_count = 0;
|
||||
|
||||
EFMCR &=0xFFFF0001; // set wait state 1
|
||||
|
||||
#if defined(TRIM_IRC)
|
||||
/* if not trimmed, do trim first */
|
||||
ICS_Trim(ICS_TRIM_VALUE);
|
||||
#endif
|
||||
/*
|
||||
* Enable SWD pin, RESET pin
|
||||
*/
|
||||
/*
|
||||
* NOTE: please make sure other register bits are also write-once and
|
||||
* need add other bit mask here if needed.
|
||||
*/
|
||||
#if defined(SPI0_PINREMAP)
|
||||
sSIMConfig.u32PinSel |= SIM_PINSEL_SPI0PS_MASK;
|
||||
#endif
|
||||
|
||||
#if defined(OUTPUT_BUSCLK)
|
||||
sSIMConfig.sBits.bEnableCLKOUT = 1; /* output bus clock if enabled */
|
||||
#endif
|
||||
|
||||
#if defined(DISABLE_NMI)
|
||||
sSIMConfig.sBits.bDisableNMI = 1;
|
||||
#endif
|
||||
|
||||
/* make sure clocks to peripheral modules are enabled */
|
||||
sSIMConfig.u32SCGC |= SIM_SCGC_SWD_MASK | SIM_SCGC_FLASH_MASK |
|
||||
SIM_SCGC_UART0_MASK | SIM_SCGC_UART1_MASK |
|
||||
SIM_SCGC_UART2_MASK;
|
||||
|
||||
sSIMConfig.sBits.bBusDiv |= BUSDIV_ENCODE;
|
||||
|
||||
|
||||
SIM_Init(&sSIMConfig); /* initialize SIM */
|
||||
|
||||
#if defined(XOSC_STOP_ENABLE)
|
||||
sICSConfig.oscConfig.bStopEnable = 1; /* enabled in stop mode */
|
||||
#endif
|
||||
|
||||
#if defined(CRYST_HIGH_GAIN)
|
||||
sICSConfig.oscConfig.bGain = 1; /* high gain */
|
||||
#endif
|
||||
|
||||
|
||||
#if (EXT_CLK_FREQ_KHZ >=4000)
|
||||
sICSConfig.oscConfig.bRange = 1; /* high range */
|
||||
#endif
|
||||
|
||||
sICSConfig.oscConfig.bEnable = 1; /* enable OSC */
|
||||
sICSConfig.u32ClkFreq = EXT_CLK_FREQ_KHZ;
|
||||
|
||||
#if defined(USE_FEE)
|
||||
sICSConfig.u8ClkMode = ICS_CLK_MODE_FEE;
|
||||
#elif defined(USE_FBE_OSC)
|
||||
sICSConfig.u8ClkMode = ICS_CLK_MODE_FBE_OSC;
|
||||
#elif defined(USE_FEE_OSC)
|
||||
sICSConfig.u8ClkMode = ICS_CLK_MODE_FEE_OSC;
|
||||
#elif defined(USE_FBILP)
|
||||
sICSConfig.u8ClkMode = ICS_CLK_MODE_FBILP;
|
||||
#elif defined(USE_FBELP)
|
||||
sICSConfig.u8ClkMode = ICS_CLK_MODE_FBELP;
|
||||
#endif
|
||||
|
||||
ICS_Init(&sICSConfig); /* initialize ICS */
|
||||
|
||||
/* initialize UART for printing */
|
||||
//UART_InitPrint();
|
||||
|
||||
#if defined(PRINT_SYS_LOG)
|
||||
//print_sys_log();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: print_sys_log
|
||||
*
|
||||
* @brief print system reset sources
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
void print_sys_log(void)
|
||||
{
|
||||
uint8_t u8Rst = 0;
|
||||
uint8_t u8FamID,u8SubFamID,u8RevID,u8PinID;
|
||||
uint32_t u32Status;
|
||||
|
||||
u32Status = SIM_GetStatus(0xFF); /* get all status bits */
|
||||
|
||||
/* get all IDs */
|
||||
u8FamID = SIM_ReadID(ID_TYPE_FAMID);
|
||||
u8SubFamID = SIM_ReadID(ID_TYPE_SUBFAMID);
|
||||
u8RevID = SIM_ReadID(ID_TYPE_REVID);
|
||||
u8PinID = SIM_ReadID(ID_TYPE_PINID);
|
||||
|
||||
printf("\n\n--System Log BEGINS--\n\n");
|
||||
printf("\n Familly ID = 0x%x, Sub-family ID = 0x%x, Revision ID = 0x%x, Pin ID = 0x%x \n",
|
||||
u8FamID, u8SubFamID, u8RevID, u8PinID);
|
||||
|
||||
if((u32Status & SIM_SRSID_POR_MASK) && (u32Status & SIM_SRSID_LVD_MASK))
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" Power On Reset\n");
|
||||
}
|
||||
|
||||
if(!(u32Status & SIM_SRSID_POR_MASK) && (u32Status & SIM_SRSID_LVD_MASK))
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" LVD Reset\n");
|
||||
}
|
||||
|
||||
if(u32Status & SIM_SRSID_WDOG_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" WDOG Reset\n");
|
||||
}
|
||||
|
||||
|
||||
if(u32Status & SIM_SRSID_PIN_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" Pin Reset\n");
|
||||
}
|
||||
if(u32Status & SIM_SRSID_LOC_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" Loss of Clock Reset\n");
|
||||
}
|
||||
if(u32Status & SIM_SRSID_SACKERR_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" Stop Mode Acknowledge Error Reset\n");
|
||||
}
|
||||
if(u32Status & SIM_SRSID_MDMAP_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" MDM-AP System Reset Request\n");
|
||||
}
|
||||
if(u32Status & SIM_SRSID_SW_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" Software/SYSRESETREQ Reset\n");
|
||||
}
|
||||
if(u32Status & SIM_SRSID_LOCKUP_MASK)
|
||||
{
|
||||
u8Rst = 1;
|
||||
printf(" Core lockup Reset\n");
|
||||
}
|
||||
|
||||
if(u8Rst != 1)
|
||||
{
|
||||
printf("SWD Reset\n");
|
||||
}
|
||||
|
||||
printf("\n--System Log ENDS--\n\n");
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: end_test
|
||||
*
|
||||
* @brief print test result (pass/fail counts) after end of test
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
|
||||
void end_test(void)
|
||||
{
|
||||
|
||||
if(global_fail_count==0){
|
||||
printf("\n global_pass_count = 0x%02x%02x",(uint8)(global_pass_count>>8),(uint8)global_pass_count);
|
||||
printf("\n\n TEST PASSED");
|
||||
} else{
|
||||
printf("\n global_pass_count = 0x%02x%02x",(uint8)(global_pass_count>>8),(uint8)global_pass_count);
|
||||
printf("\n global_fail_count = 0x%02x%02x",(uint8)(global_fail_count>>8),(uint8)global_fail_count);
|
||||
printf("\n\n TEST FAILED");
|
||||
}
|
||||
|
||||
printf("\n\n TEST FINISHED");
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: UART_InitPrint
|
||||
*
|
||||
* @brief initialize UART for print on port defined by TERM_PORT.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
|
||||
void UART_InitPrint(void)
|
||||
{
|
||||
UART_ConfigType sConfig;
|
||||
|
||||
sConfig.u32SysClkHz = BUS_CLK_HZ;
|
||||
sConfig.u32Baudrate = UART_PRINT_BITRATE;
|
||||
|
||||
SIM_RemapUART0Pin();
|
||||
|
||||
UART_Init (TERM_PORT, &sConfig);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/******************************************************************************
|
||||
* @brief provide system init routine/configuration for KExx.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#ifndef SYSINIT_H_
|
||||
#define SYSINIT_H_
|
||||
|
||||
/******************************************************************************
|
||||
* Includes
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Constants
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Macros
|
||||
******************************************************************************/
|
||||
#define SIM_SCGC_VALUE 0x00003000L
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Global variables
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Global functions
|
||||
******************************************************************************/
|
||||
void sysinit (void);
|
||||
void enable_abort_button(void);
|
||||
void end_test(void);
|
||||
|
||||
/********************************************************************/
|
||||
#endif /* SYSINIT_H_ */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
** ###################################################################
|
||||
*
|
||||
* Provides a system configuration function and a global variable that contains
|
||||
* the system frequency. It configures the device and initializes the oscillator
|
||||
* (PLL) that is part of the microcontroller device.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_MKE02Z2_H_
|
||||
#define SYSTEM_MKE02Z2_H_ /**< Symbol preventing repeated inclusion */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief System clock frequency (core clock)
|
||||
*
|
||||
* The system clock frequency supplied to the SysTick timer and the processor
|
||||
* core clock. This variable can be used by the user application to setup the
|
||||
* SysTick timer or configure other parameters. It may also be used by debugger to
|
||||
* query the frequency of the debug timer or configure the trace clock speed
|
||||
* SystemCoreClock is initialized with a correct predefined value.
|
||||
*/
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system.
|
||||
*
|
||||
* Typically this function configures the oscillator (PLL) that is part of the
|
||||
* microcontroller device. For systems with variable clock speed it also updates
|
||||
* the variable SystemCoreClock. SystemInit is called from startup_device file.
|
||||
*/
|
||||
void SystemInit (void);
|
||||
|
||||
/**
|
||||
* @brief Updates the SystemCoreClock variable.
|
||||
*
|
||||
* It must be called whenever the core clock is changed during program
|
||||
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
|
||||
* the current core clock.
|
||||
*/
|
||||
void SystemCoreClockUpdate (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if !defined(SYSTEM_MKE02Z2_H_) */
|
||||
@@ -0,0 +1,89 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide systick utility routines.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "systick.h"
|
||||
//#include "stdint.h"
|
||||
uint32_t cnt_start_value;
|
||||
uint32_t cnt_end_value;
|
||||
uint32_t overhead;
|
||||
SysTick_CallbackType SysTick_Callback[1] = {NULL};
|
||||
#if 0
|
||||
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
|
||||
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
|
||||
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
|
||||
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
|
||||
#endif
|
||||
void systick_init(void)
|
||||
{
|
||||
|
||||
SysTick->VAL = 0x0; /* clear current ETMer value */
|
||||
SysTick->LOAD = 0x00FFFFFF;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||
}
|
||||
|
||||
void SysTick_SetCallBack(SysTick_CallbackType pSysTick_CallBack)
|
||||
{
|
||||
SysTick_Callback[0] = pSysTick_CallBack;
|
||||
}
|
||||
|
||||
/***
|
||||
void delay_us(int n)//微秒级别的延时
|
||||
{
|
||||
int temp;
|
||||
SysTick->LOAD= 48 *n; //????
|
||||
SysTick->VAL=0x00000000; //?????
|
||||
SysTick->CTRL=0x00000005;
|
||||
while(SysTick->CTRL&0x00010000); //????
|
||||
SysTick->CTRL=0x00000004;
|
||||
}
|
||||
***/
|
||||
|
||||
/****
|
||||
void delay_ms(int n)//毫秒级别的延时
|
||||
{
|
||||
int temp;
|
||||
SysTick->LOAD= 48000 *n; //????
|
||||
SysTick->VAL=0x00000000; //?????
|
||||
SysTick->CTRL=0x00000005;
|
||||
while(SysTick->CTRL&0x00010000); //????
|
||||
SysTick->CTRL=0x00000004;
|
||||
}******////
|
||||
|
||||
void systick_disable(void)
|
||||
{
|
||||
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
|
||||
}
|
||||
|
||||
void cal_systick_read_overhead(void)
|
||||
{
|
||||
uint32_t cnt_start_value;
|
||||
uint32_t cnt_end_value;
|
||||
|
||||
cnt_start_value = SysTick->VAL;
|
||||
|
||||
cnt_end_value = SysTick->VAL;
|
||||
|
||||
overhead = cnt_start_value - cnt_end_value;
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
printf("systick start value: 0x%x\n\r", (unsigned int)cnt_start_value);
|
||||
printf("systick end value: 0x%x\n\r", (unsigned int) cnt_end_value);
|
||||
printf("systick current value read overhead: 0x%x\n\r", (unsigned int)overhead);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SysTick_Isr(void)
|
||||
{
|
||||
//printf("input any character to start a new conversion!\n");
|
||||
if( SysTick_Callback[0] )
|
||||
{
|
||||
SysTick_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/******************************************************************************
|
||||
* @brief provide systick utility routines.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __SYSTICK_H
|
||||
#define __SYSTICK_H
|
||||
typedef void (*SysTick_CallbackType)(void);
|
||||
|
||||
#define SYS_COUNT_ETME 10 //ms
|
||||
#define SYS_COUNT MCU_CLCOK*SYS_COUNT_ETME/16
|
||||
/* Global variables */
|
||||
extern uint32_t cnt_start_value;
|
||||
extern uint32_t cnt_end_value;
|
||||
extern uint32_t overhead;
|
||||
void SysTick_SetCallBack(SysTick_CallbackType pSysTick_CallBack);
|
||||
|
||||
/* Function declaration */
|
||||
void systick_init(void);
|
||||
void systick_disable(void);
|
||||
void cal_systick_read_overhead(void);
|
||||
//void delay_us(int n);
|
||||
//void delay_ms(int n);
|
||||
void SysTick_SetCallBack(SysTick_CallbackType pSysTick_CallBack);
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief provide interrupt vector table for NV32Fxxx.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "vectors.h"
|
||||
#include "isr.h"
|
||||
#include "common.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Vector Table
|
||||
******************************************************************************/
|
||||
typedef void (*vector_entry)(void);
|
||||
|
||||
#ifdef KEIL
|
||||
const vector_entry __vector_table[] __attribute__((at(0x00))) =
|
||||
#elif (defined(__GNUC__))
|
||||
//void (* const __vector_table[])() __attribute__ ((section(".vectortable"))) =
|
||||
void (* const InterruptVector[])() __attribute__ ((section(".isr_vector"))) =
|
||||
#else
|
||||
#pragma location = ".intvec"
|
||||
const vector_entry __vector_table[] = //@ ".intvec" =
|
||||
#endif
|
||||
{
|
||||
VECTOR_000, /* Initial SP */
|
||||
VECTOR_001, /* Initial PC */
|
||||
VECTOR_002,
|
||||
VECTOR_003,
|
||||
VECTOR_004,
|
||||
VECTOR_005,
|
||||
VECTOR_006,
|
||||
VECTOR_007,
|
||||
VECTOR_008,
|
||||
VECTOR_009,
|
||||
VECTOR_010,
|
||||
VECTOR_011,
|
||||
VECTOR_012,
|
||||
VECTOR_013,
|
||||
VECTOR_014,
|
||||
VECTOR_015,
|
||||
VECTOR_016,
|
||||
VECTOR_017,
|
||||
VECTOR_018,
|
||||
VECTOR_019,
|
||||
VECTOR_020,
|
||||
VECTOR_021,
|
||||
VECTOR_022,
|
||||
VECTOR_023,
|
||||
VECTOR_024,
|
||||
VECTOR_025,
|
||||
VECTOR_026,
|
||||
VECTOR_027,
|
||||
VECTOR_028,
|
||||
VECTOR_029,
|
||||
VECTOR_030,
|
||||
VECTOR_031,
|
||||
VECTOR_032,
|
||||
VECTOR_033,
|
||||
VECTOR_034,
|
||||
VECTOR_035,
|
||||
VECTOR_036,
|
||||
VECTOR_037,
|
||||
VECTOR_038,
|
||||
VECTOR_039,
|
||||
VECTOR_040,
|
||||
VECTOR_041,
|
||||
VECTOR_042,
|
||||
VECTOR_043,
|
||||
VECTOR_044,
|
||||
VECTOR_045,
|
||||
VECTOR_046,
|
||||
VECTOR_047 // END of real vector table
|
||||
};
|
||||
// VECTOR_TABLE end
|
||||
#ifndef KEIL
|
||||
#ifndef USE_BOOTLOADER
|
||||
#ifdef KEIL
|
||||
const uint32_t __flash_config[] __attribute__((at(0x400))) =
|
||||
#elif (defined(__GNUC__))
|
||||
const uint32_t __flash_config[] __attribute__ ((section(".nv32_flash_config_field"))) =
|
||||
#else
|
||||
#pragma location = 0x400
|
||||
__root const uint32_t __flash_config[] = //@ ".intvec" =
|
||||
#endif
|
||||
{
|
||||
CONFIG_1,
|
||||
CONFIG_2,
|
||||
CONFIG_3,
|
||||
CONFIG_4,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* default_isr(void)
|
||||
*
|
||||
* Default ISR definition.
|
||||
*
|
||||
* In: n/a
|
||||
* Out: n/a
|
||||
******************************************************************************/
|
||||
void default_isr(void)
|
||||
{
|
||||
#define VECTORNUM (*(volatile uint32_t*)(0xE000ED04))
|
||||
|
||||
printf("\n****default_isr entered on vector %lu*****\r\n\n",VECTORNUM);
|
||||
return;
|
||||
}
|
||||
/******************************************************************************/
|
||||
/* Generic interrupt handler for a GPIO interrupt connected to an
|
||||
* abort switch.
|
||||
* NOTE: For true abort operation this handler should be modified
|
||||
* to jump to the main process instead of executing a return.
|
||||
*/
|
||||
void abort_isr(void)
|
||||
{
|
||||
//printf("\n****Abort button interrupt****\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Exception frame without floating-point storage
|
||||
* hard fault handler in C,
|
||||
* with stack frame location as input parameter
|
||||
*/
|
||||
void
|
||||
hard_fault_handler_c(unsigned int * hardfault_args)
|
||||
{
|
||||
/*
|
||||
unsigned int stacked_r0;
|
||||
unsigned int stacked_r1;
|
||||
unsigned int stacked_r2;
|
||||
unsigned int stacked_r3;
|
||||
unsigned int stacked_r12;
|
||||
unsigned int stacked_lr;
|
||||
unsigned int stacked_pc;
|
||||
unsigned int stacked_psr;
|
||||
|
||||
//Exception stack frame
|
||||
stacked_r0 = ((unsigned long) hardfault_args[0]);
|
||||
stacked_r1 = ((unsigned long) hardfault_args[1]);
|
||||
stacked_r2 = ((unsigned long) hardfault_args[2]);
|
||||
stacked_r3 = ((unsigned long) hardfault_args[3]);
|
||||
|
||||
stacked_r12 = ((unsigned long) hardfault_args[4]);
|
||||
stacked_lr = ((unsigned long) hardfault_args[5]);
|
||||
stacked_pc = ((unsigned long) hardfault_args[6]);
|
||||
stacked_psr = ((unsigned long) hardfault_args[7]);
|
||||
|
||||
printf ("[Hard fault handler]\n");
|
||||
printf ("R0 = %x\n", stacked_r0);
|
||||
printf ("R1 = %x\n", stacked_r1);
|
||||
printf ("R2 = %x\n", stacked_r2);
|
||||
printf ("R3 = %x\n", stacked_r3);
|
||||
printf ("R12 = %x\n", stacked_r12);
|
||||
printf ("LR = %x\n", stacked_lr);
|
||||
printf ("PC = %x\n", stacked_pc);
|
||||
printf ("PSR = %x\n", stacked_psr);
|
||||
printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
|
||||
printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
|
||||
printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
|
||||
printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
|
||||
printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
|
||||
*/
|
||||
//for(;;)
|
||||
//;/*infinite loop*/
|
||||
}
|
||||
|
||||
|
||||
/* End of "vectors.c" */
|
||||
@@ -0,0 +1,146 @@
|
||||
/******************************************************************************
|
||||
* @brief provide interrupt vector table for NV32Fxxx
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __VECTORS_H
|
||||
#define __VECTORS_H 1
|
||||
|
||||
// function prototype for default_isr in vectors.c
|
||||
void default_isr(void);
|
||||
void abort_isr(void);
|
||||
|
||||
|
||||
void hard_fault_handler_c(unsigned int * hardfault_args);
|
||||
|
||||
/* Interrupt Vector Table Function Pointers */
|
||||
typedef void pointer(void);
|
||||
|
||||
extern void __startup(void);
|
||||
extern unsigned long __BOOT_STACK_ADDRESS[];
|
||||
extern unsigned long __initial_sp[];
|
||||
extern void Reset_Handler( void );
|
||||
#if (defined(__GNUC__))
|
||||
extern unsigned long _estack;
|
||||
extern void Reset_Handler(void);
|
||||
#define VECTOR_000 (pointer*)&_estack // ARM core Initial Supervisor SP
|
||||
#define VECTOR_001 Reset_Handler // 0x0000_0004 1 - ARM core Initial Program Counter
|
||||
#elif (defined(KEIL))
|
||||
#define VECTOR_000 (pointer*)__initial_sp // ARM core Initial Supervisor SP
|
||||
#define VECTOR_001 Reset_Handler // 0x0000_0004 1 - ARM core Initial Program Counter
|
||||
#else
|
||||
// Address Vector IRQ Source module Source description
|
||||
#define VECTOR_000 (pointer*)__BOOT_STACK_ADDRESS // ARM core Initial Supervisor SP
|
||||
#define VECTOR_001 __startup // 0x0000_0004 1 - ARM core Initial Program Counter
|
||||
#endif
|
||||
#define VECTOR_002 default_isr // 0x0000_0008 2 - ARM core Non-maskable Interrupt (NMI)
|
||||
#define VECTOR_003 default_isr // 0x0000_000C 3 - ARM core Hard Fault
|
||||
#define VECTOR_004 default_isr // 0x0000_0010 4 -
|
||||
#define VECTOR_005 default_isr // 0x0000_0014 5 - ARM core Bus Fault
|
||||
#define VECTOR_006 default_isr // 0x0000_0018 6 - ARM core Usage Fault
|
||||
#define VECTOR_007 default_isr // 0x0000_001C 7 -
|
||||
#define VECTOR_008 default_isr // 0x0000_0020 8 -
|
||||
#define VECTOR_009 default_isr // 0x0000_0024 9 -
|
||||
#define VECTOR_010 default_isr // 0x0000_0028 10 -
|
||||
#define VECTOR_011 default_isr // 0x0000_002C 11 - ARM core Supervisor call (SVCall)
|
||||
#define VECTOR_012 default_isr // 0x0000_0030 12 - ARM core Debug Monitor
|
||||
#define VECTOR_013 default_isr // 0x0000_0034 13 -
|
||||
#define VECTOR_014 default_isr // 0x0000_0038 14 - ARM core Pendable request for system service (PendableSrvReq)
|
||||
#define VECTOR_015 default_isr // 0x0000_003C 15 - ARM core System tick ETMer (SysTick)
|
||||
#define VECTOR_016 default_isr // 0x0000_0040 16 0 Reserved DMA DMA Channel 0 transfer complete
|
||||
#define VECTOR_017 default_isr // 0x0000_0044 17 1 Reserved DMA DMA Channel 1 transfer complete
|
||||
#define VECTOR_018 default_isr // 0x0000_0048 18 2 Reserved DMA DMA Channel 2 transfer complete
|
||||
#define VECTOR_019 default_isr // 0x0000_004C 19 3 Reserved DMA DMA Channel 3 transfer complete
|
||||
#define VECTOR_020 default_isr // 0x0000_0050 20 4 Reserved MCM MCM
|
||||
#define VECTOR_021 default_isr // 0x0000_0054 21 5 NVM ETMRH flash memory command complete,ECC fault
|
||||
#define VECTOR_022 default_isr // 0x0000_0058 22 6 PMC LVD,LVW interrupt
|
||||
#define VECTOR_023 default_isr // 0x0000_005C 23 7 LLWU LLWU/IRQ
|
||||
#define VECTOR_024 default_isr // 0x0000_0060 24 8 I2C0 I2C
|
||||
#define VECTOR_025 default_isr // 0x0000_0064 25 9 - --
|
||||
#define VECTOR_026 default_isr // 0x0000_0068 26 10 SPI0 SPI0
|
||||
#define VECTOR_027 default_isr // 0x0000_006C 27 11 SPI1 SPI1
|
||||
#define VECTOR_028 default_isr // 0x0000_0070 28 12 SCI0 UART0
|
||||
#define VECTOR_029 default_isr // 0x0000_0074 29 13 SCI1 UART1
|
||||
#define VECTOR_030 default_isr // 0x0000_0078 30 14 SCI2 UART2
|
||||
#define VECTOR_031 default_isr // 0x0000_007C 31 15 ADC0 ADC conversion complete
|
||||
#define VECTOR_032 default_isr // 0x0000_0080 32 16 ACMP0 ACMP0
|
||||
#define VECTOR_033 default_isr // 0x0000_0084 33 17 ETM0 FlexETMer0
|
||||
#define VECTOR_034 default_isr // 0x0000_0088 34 18 ETM1 FlexETMer1
|
||||
#define VECTOR_035 default_isr // 0x0000_008C 35 19 ETM2 FlexETMer2
|
||||
#define VECTOR_036 default_isr // 0x0000_0090 36 20 RTC RTC overflow
|
||||
#define VECTOR_037 default_isr // 0x0000_0094 37 21 ACMP1 ACMP1
|
||||
#define VECTOR_038 default_isr // 0x0000_0098 38 22 PIT_CH0 PIT_CH0 overflow
|
||||
#define VECTOR_039 default_isr // 0x0000_009C 39 23 PIT_CH1 PIT_CH1 overflow
|
||||
#define VECTOR_040 default_isr // 0x0000_00A0 40 24 KBI0 Keyboard0 interrupt
|
||||
#define VECTOR_041 default_isr // 0x0000_00A4 41 25 KBI1 Keyboard1 interrupt
|
||||
#define VECTOR_042 default_isr // 0x0000_00A8 42 26 Reserved ---
|
||||
#define VECTOR_043 default_isr // 0x0000_00AC 43 27 ICS ICS loss of lock
|
||||
#define VECTOR_044 default_isr // 0x0000_00B0 44 28 WDOG Watchdog ETMeout
|
||||
#define VECTOR_045 default_isr // 0x0000_00B4 45 29 Reserved
|
||||
#define VECTOR_046 default_isr // 0x0000_00B8 46 30 Reserved
|
||||
#define VECTOR_047 default_isr // 0x0000_00BC 47 31 Reserved // END of real vector table
|
||||
/********************************************************************************************************************/
|
||||
#define VECTOR_048 default_isr // 0x0000_00C0 48 32 Reserved
|
||||
#define VECTOR_049 default_isr // 0x0000_00C4 49 33 Reserved
|
||||
#define VECTOR_050 default_isr // 0x0000_00C8 50 34 Reserved
|
||||
#define VECTOR_051 default_isr // 0x0000_00CC 51 35 Reserved
|
||||
#define VECTOR_052 default_isr // 0x0000_00D0 52 36 Reserved
|
||||
#define VECTOR_053 default_isr // 0x0000_00D4 53 37 Reserved
|
||||
#define VECTOR_054 default_isr // 0x0000_00D8 54 38 Reserved
|
||||
#define VECTOR_055 default_isr // 0x0000_00DC 55 39 Reserved
|
||||
#define VECTOR_056 default_isr // 0x0000_00E0 56 40 Reserved
|
||||
#define VECTOR_057 default_isr // 0x0000_00E4 57 41 Reserved
|
||||
#define VECTOR_058 default_isr // 0x0000_00E8 58 42 Reserved
|
||||
#define VECTOR_059 default_isr // 0x0000_00EC 59 43 Reserved
|
||||
#define VECTOR_060 default_isr // 0x0000_00F0 60 44 Reserved
|
||||
#define VECTOR_061 default_isr // 0x0000_00F4 61 45 Reserved Single interrupt vector for SCI status sources
|
||||
#define VECTOR_062 default_isr // 0x0000_00F8 62 46 Reserved Single interrupt vector for SCI error sources
|
||||
#define VECTOR_063 default_isr // 0x0000_00FC 63 47 Reserved Single interrupt vector for SCI status sources
|
||||
#define VECTOR_064 default_isr // 0x0000_0100 64 48 Reserved Single interrupt vector for SCI error sources
|
||||
#define VECTOR_065 default_isr // 0x0000_0104 65 49 Reserved Single interrupt vector for SCI status sources
|
||||
#define VECTOR_066 default_isr // 0x0000_0108 66 50 Reserved Single interrupt vector for SCI error sources
|
||||
#define VECTOR_067 default_isr // 0x0000_010C 67 51 Reserved Single interrupt vector for SCI status sources
|
||||
#define VECTOR_068 default_isr // 0x0000_0110 68 52 Reserved Single interrupt vector for SCI error sources
|
||||
#define VECTOR_069 default_isr // 0x0000_0114 69 53 Reserved Single interrupt vector for SCI status sources
|
||||
#define VECTOR_070 default_isr // 0x0000_0118 70 54 Reserved Single interrupt vector for SCI error sources
|
||||
#define VECTOR_071 default_isr // 0x0000_011C 71 55 Reserved Single interrupt vector for SCI status sources
|
||||
#define VECTOR_072 default_isr // 0x0000_0120 72 56 Reserved Single interrupt vector for SCI error sources
|
||||
#define VECTOR_073 default_isr // 0x0000_0124 73 57 Reserved
|
||||
#define VECTOR_074 default_isr // 0x0000_0128 74 58 Reserved
|
||||
#define VECTOR_075 default_isr // 0x0000_012C 75 59 Reserved
|
||||
#define VECTOR_076 default_isr // 0x0000_0130 76 60 Reserved
|
||||
#define VECTOR_077 default_isr // 0x0000_0134 77 61 Reserved
|
||||
#define VECTOR_078 default_isr // 0x0000_0138 78 62 Reserved Single interrupt vector for all sources
|
||||
#define VECTOR_079 default_isr // 0x0000_013C 79 63 Reserved Single interrupt vector for all sources
|
||||
#define VECTOR_080 default_isr // 0x0000_0140 80 64 Reserved Single interrupt vector for all sources
|
||||
#define VECTOR_081 default_isr // 0x0000_0144 81 65 Reserved
|
||||
#define VECTOR_082 default_isr // 0x0000_0148 82 66 Reserved
|
||||
#define VECTOR_083 default_isr // 0x0000_014C 83 67
|
||||
#define VECTOR_084 default_isr // 0x0000_0150 84 68
|
||||
#define VECTOR_085 default_isr // 0x0000_0154 85 69
|
||||
#define VECTOR_086 default_isr // 0x0000_0158 86 70
|
||||
#define VECTOR_087 default_isr // 0x0000_015C 87 71
|
||||
#define VECTOR_088 default_isr // 0x0000_0160 88 72
|
||||
#define VECTOR_089 default_isr // 0x0000_0164 89 73
|
||||
#define VECTOR_090 default_isr // 0x0000_0168 90 74
|
||||
#define VECTOR_091 default_isr // 0x0000_016C 91 75
|
||||
#define VECTOR_092 default_isr // 0x0000_0170 92 76
|
||||
#define VECTOR_093 default_isr // 0x0000_0174 93 77
|
||||
#define VECTOR_094 default_isr // 0x0000_0178 94 78
|
||||
#define VECTOR_095 default_isr // 0x0000_017C 95 79
|
||||
#define VECTOR_096 default_isr // 0x0000_0180 96 80
|
||||
#define VECTOR_097 default_isr // 0x0000_0184 97 81
|
||||
#define VECTOR_098 default_isr // 0x0000_0188 98 82
|
||||
#define VECTOR_099 default_isr // 0x0000_018C 99 83
|
||||
|
||||
#ifdef USE_BOOTLOADER
|
||||
#else
|
||||
#define CONFIG_1 0xffffffff
|
||||
#define CONFIG_2 0xffffffff
|
||||
#define CONFIG_3 0xffffffff
|
||||
#define CONFIG_4 0xfffeffff
|
||||
#endif
|
||||
#endif /*__VECTORS_H*/
|
||||
|
||||
/* End of "vectors.h" */
|
||||
@@ -0,0 +1,11 @@
|
||||
lemcu.org GPL Exception version 1.0
|
||||
-----------------------------------
|
||||
|
||||
As an additional permission, if Lemcusb library is statically linked with one or more of the following
|
||||
software libraries, then, these software libraries are not subjected to the TERMS AND CONDITIONS of
|
||||
GNU General Public License version 3.0.
|
||||
|
||||
(1) Silicon Laboratories Inc's "emlib", "emdrv", any software supplied as part of application note and/or examples.
|
||||
(2) ARM Limited's "CMSIS".
|
||||
|
||||
They are bound by their own terms and conditions as specified by their authors.
|
||||
@@ -0,0 +1,681 @@
|
||||
The Lemcusb is Copyright (C) 2014 http://lemcu.org
|
||||
|
||||
You may use, distribute and copy the Lemcusb under the terms of
|
||||
GNU General Public License version 3.0, which is displayed below.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __C_COMPAT_H__
|
||||
#define __C_COMPAT_H__
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#define RAMFUNC __ramfunc
|
||||
#else
|
||||
#define RAMFUNC __attribute__((__long_call__)) __attribute__((section(".functioninRAM"))) __attribute__ ((noinline))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,381 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "usb.h"
|
||||
//#include "em_device.h"
|
||||
//#include "em_cmu.h"
|
||||
//#include "em_int.h"
|
||||
//#include "em_timer.h"
|
||||
#include "gpio.h"
|
||||
#include "usb_internal_ll.h"
|
||||
#include "usb_stack.h"
|
||||
#include "usb_helperfunctions.h"
|
||||
|
||||
|
||||
void usb_reset_received(void)
|
||||
{
|
||||
uint32_t cnt;
|
||||
uint32_t *ptr;
|
||||
|
||||
GPIOA->PSOR = (1<<1);
|
||||
|
||||
/* zero intitialize endpoint buffers and len/status fields */
|
||||
ptr = (uint32_t *)usb_ep_buffers;
|
||||
for (cnt=0; cnt < (sizeof(usb_ep_buffers)>>2); cnt++)
|
||||
{
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
/* preinitialize DATA PIDS for IN endpoints */
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF] = 0x4B;
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF] = 0x4B;
|
||||
|
||||
/* reset usb device address to 0 (will be changed during enumeration) */
|
||||
usbstack_init();
|
||||
GPIOA->PSOR = (1<<1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pinout information:
|
||||
* PA2 = D-
|
||||
* PA3 = D+
|
||||
* PA1 = debug output (to scope)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pre-condition: GPIO clock enabled
|
||||
*
|
||||
*/
|
||||
void usb_init(void)
|
||||
{
|
||||
usb_reset_received();
|
||||
|
||||
/* Pinout: PA1 = USB connect line (1k5 resistor to PC0)
|
||||
PA2 = D-
|
||||
PA3 = D+
|
||||
*/
|
||||
/* set PA0 low (disconnected) Will enable the pulldown */
|
||||
GPIOA->PCOR = (1 << 2);
|
||||
/* Pin PA0 is configured to Input enabled with pull-down */
|
||||
//GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;
|
||||
|
||||
/* Pin PC0 is configured to Input enabled */
|
||||
//GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUT;
|
||||
/* Pin PC1 is configured to Input enabled */
|
||||
// GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE1_MASK) | GPIO_P_MODEL_MODE1_INPUT;
|
||||
|
||||
/* set output state of PC0 PC1 (D- D+) to 1 0 */
|
||||
GPIOA->PSOR = (1<<2); /* D- = 1 */
|
||||
GPIOA->PCOR = (1<<3); /* D+ = 0 */
|
||||
|
||||
/* Pin PE13 is configured to Push-pull */
|
||||
//GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE13_MASK) | GPIO_P_MODEH_MODE13_PUSHPULL;
|
||||
|
||||
/* setup PC1 interrupt on rising edge (D+ first SYNC bit) */
|
||||
/* Configure PC1 interrupt on rising edge */
|
||||
// GPIO_IntConfig(gpioPortC, 1, true, false, true);
|
||||
/* Set Interrupt priority to highest */
|
||||
// NVIC_SetPriority(GPIO_ODD_IRQn, 0);
|
||||
/* Enable GPIO_EVEN interrupt vector in NVIC */
|
||||
// NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
||||
}
|
||||
|
||||
void usb_connect(void)
|
||||
{
|
||||
GPIOA->PSOR = (1 << 3);
|
||||
//GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_PUSHPULL;
|
||||
}
|
||||
|
||||
void usb_disconnect(void)
|
||||
{
|
||||
/* Pin PA0 is configured to Input enabled with pull-down */
|
||||
// GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;
|
||||
/* set PA0 low (disconnected) Will enable the pulldown */
|
||||
GPIOA->PCOR = (1 << 3);
|
||||
}
|
||||
|
||||
bool usb_check_resetcondition(void)
|
||||
{
|
||||
return ( (GPIOA->PDIR & 0x00000006) == 0x00 );
|
||||
}
|
||||
|
||||
/* check if a setup packet was received */
|
||||
bool usb_setup_available(void)
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
|
||||
}
|
||||
|
||||
/* IDEA: The reordering / Bitreversal can be done in place to save some RAM */
|
||||
void usb_setup_get_data(setupData_t *psetupdata)
|
||||
{
|
||||
uint32_t i, j;
|
||||
uint8_t dat;
|
||||
uint8_t setupdat[8];
|
||||
volatile uint8_t *SETUP_BUF;
|
||||
|
||||
SETUP_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF];
|
||||
for (i=0; i<8; i++) /* walk through all bytes */
|
||||
{
|
||||
j = i+1;
|
||||
j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
|
||||
dat = SETUP_BUF[j];
|
||||
dat = bitreverse(dat); /* reverse bits*/
|
||||
setupdat[i] = dat; /* store data */
|
||||
}
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* flag setup data as empty */
|
||||
|
||||
psetupdata->bmRequestType = setupdat[0];
|
||||
psetupdata->bRequest = setupdat[1];
|
||||
psetupdata->wValue = setupdat[2];
|
||||
psetupdata->wValue |= setupdat[3] << 8;
|
||||
psetupdata->wIndex = setupdat[4];
|
||||
psetupdata->wIndex |= setupdat[5] << 8;
|
||||
psetupdata->wLength = setupdat[6];
|
||||
psetupdata->wLength |= setupdat[7] << 8;
|
||||
}
|
||||
|
||||
bool usb_ep_in_buf_empty(uint32_t epnum)
|
||||
{
|
||||
if (epnum)
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO/IDEA: check parameters like len. This can be done e.g. with ASSERTIONS, so
|
||||
* that checks can be disabled later to save time & space
|
||||
*/
|
||||
void usb_ep_in_commit_pkt(uint32_t epnum, bool firstpkt, const uint8_t *pbuf, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t dat;
|
||||
uint16_t crc_value;
|
||||
volatile uint8_t *EP0IN_BUF;
|
||||
|
||||
if (!len)
|
||||
{
|
||||
GPIOA->PSOR = (1<<8);
|
||||
GPIOA->PCOR = (1<<8);
|
||||
}
|
||||
|
||||
if (epnum)
|
||||
{
|
||||
EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF];
|
||||
}
|
||||
else
|
||||
{
|
||||
EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF];
|
||||
}
|
||||
|
||||
if (firstpkt)
|
||||
{
|
||||
EP0IN_BUF[0] = 0x4B; /* first IN packet is always transmitted with DATA1 PID */
|
||||
}
|
||||
else
|
||||
{
|
||||
EP0IN_BUF[0] ^= 0x88; /* Following packets toggle between DATA0 and DATA1 PID */
|
||||
}
|
||||
|
||||
crc_value = 0xffff;
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
dat = *pbuf++;
|
||||
EP0IN_BUF[i+1] = dat;
|
||||
crc_value = crc16(crc_value, dat);
|
||||
}
|
||||
|
||||
crc_value = ~crc_value; /* this is described in the USB spec. */
|
||||
|
||||
/* ADD CRC */
|
||||
EP0IN_BUF[1+len+0] = crc_value & 0xff; /* CRC low */
|
||||
EP0IN_BUF[1+len+1] = crc_value >> 8; /* CRC high */
|
||||
|
||||
/* set packet length */
|
||||
EP0IN_BUF[USB_EPBUF_SUBOFFSET_LEN] = len + 1 +2; /* DATAx PID + CRC16 */
|
||||
|
||||
/* Flag endpoint as "ready" for transmission. This needs to be done as the last step */
|
||||
EP0IN_BUF[USB_EPBUF_SUBOFFSET_STAT] |= (1 << 0);
|
||||
}
|
||||
|
||||
bool usb_ep_out_data_available(uint32_t epnum)
|
||||
{
|
||||
if (epnum == 0x00)
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t usb_ep_out_get_data(uint32_t epnum, uint8_t *pbuf)
|
||||
{
|
||||
uint32_t i, j, len;
|
||||
uint8_t dat, bytecount;
|
||||
volatile uint8_t *EP0OUT_BUF;
|
||||
|
||||
if (epnum == 0)
|
||||
{
|
||||
EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF];
|
||||
}
|
||||
else
|
||||
{
|
||||
EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF];
|
||||
}
|
||||
|
||||
len = EP0OUT_BUF[USB_EPBUF_SUBOFFSET_LEN];
|
||||
bytecount = ((len + 7) >> 3) - 1 - 2; /* -PID -CRC16 */
|
||||
|
||||
for (i=0; i<bytecount; i++) /* walk through all bytes */
|
||||
{
|
||||
j = i+1;
|
||||
j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
|
||||
dat = EP0OUT_BUF[j];
|
||||
dat = bitreverse(dat); /* reverse bits*/
|
||||
*pbuf++ = dat; /* store data */
|
||||
}
|
||||
|
||||
//bytecount = 0;
|
||||
|
||||
if (bytecount > 0)
|
||||
{
|
||||
volatile int i;
|
||||
i=0;
|
||||
}
|
||||
|
||||
/* flag endpoint as empty. Needs to be done as last step */
|
||||
EP0OUT_BUF[USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0);
|
||||
//usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0);
|
||||
|
||||
return bytecount;
|
||||
}
|
||||
|
||||
void usb_ep_stall(uint32_t epnum)
|
||||
{
|
||||
usb_ep_buffers[epnum + USB_EPBUF_SUBOFFSET_STAT] |= (1 << 1);
|
||||
}
|
||||
|
||||
void usb_ep_unstall(uint32_t epnum)
|
||||
{
|
||||
usb_ep_buffers[epnum + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 1);
|
||||
}
|
||||
|
||||
bool usb_ep_is_stalled(uint32_t epnum)
|
||||
{
|
||||
return (usb_ep_buffers[epnum + USB_EPBUF_SUBOFFSET_STAT] & (1 << 1));
|
||||
}
|
||||
|
||||
/* send a package via EP0IN which is longer as 7 bytes */
|
||||
void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len, bool sendshortpkt)
|
||||
{
|
||||
bool first;
|
||||
uint8_t curlen;
|
||||
|
||||
first = (epnum == 0x00); /* EP0IN packets always start with DATA1 PID, while EP1IN PID toggles between DATA0/1 */
|
||||
|
||||
curlen = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
curlen = len;
|
||||
if (curlen > 8)
|
||||
{
|
||||
curlen = 8;
|
||||
}
|
||||
while (!usb_ep_in_buf_empty(epnum)); /* wait until endpoint buffer is free */
|
||||
usb_ep_in_commit_pkt(epnum, first, pbuf, curlen);
|
||||
len -= curlen;
|
||||
pbuf += curlen;
|
||||
first = false;
|
||||
}
|
||||
if (!sendshortpkt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ((curlen == 8) || (curlen == 0)) /* in case the last packet has 8 bytes a short packet needs to be sent to signalize the host, that this was the last packet*/
|
||||
{
|
||||
while (!usb_ep_in_buf_empty(epnum)); /* wait until endpoint buffer is free */
|
||||
usb_ep_in_commit_pkt(epnum, false, pbuf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* receive a package via EP0OUT. It is allowed to be longer than 8 bytes */
|
||||
/* important: ensure, that pbuf has a buffer size with a multiple of 8 Bytes */
|
||||
/* returns received length */
|
||||
uint8_t usb_ep_out_get_data_long(uint8_t *pbuf, uint8_t maxlen)
|
||||
{
|
||||
uint8_t curlen, len;
|
||||
|
||||
curlen = 8;
|
||||
len = 0;
|
||||
do
|
||||
{
|
||||
if (usb_ep_out_data_available(0))
|
||||
{
|
||||
curlen = usb_ep_out_get_data(0, pbuf); /* TODO: Handle this within usb_stack.c. It is part of control transfers. setup */
|
||||
pbuf += curlen;
|
||||
if (len >= maxlen) /* at least a little bit of protection against buffer overruns */
|
||||
{
|
||||
pbuf -= curlen;
|
||||
}
|
||||
len += curlen;
|
||||
}
|
||||
} while ( (curlen == 8) && (len < maxlen) ); /* a short packet indicates the last packet */
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Handle a Control transfer without data stage => transmits a ACK in status stage */
|
||||
void usb_control_acknowledge(void)
|
||||
{
|
||||
uint8_t response[8];
|
||||
while (!usb_ep_in_buf_empty(0x00))
|
||||
;
|
||||
usb_ep_in_commit_pkt(0, true, response, 0);
|
||||
}
|
||||
|
||||
/* Handle a Control IN transfer */
|
||||
bool usb_control_dataIn(const uint8_t *pbuf, uint8_t len)
|
||||
{
|
||||
usb_ep_in_commit_pkt_long(0, pbuf, len, false);//true);
|
||||
/* wait for status stage - acknowledge from HOST*/
|
||||
while ( !usb_ep_out_data_available(0) )
|
||||
{
|
||||
}
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* ignore ACK (OUT packet) */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle a Control OUT transfer */
|
||||
uint8_t usb_control_dataOut(uint8_t *pbuf, uint8_t maxlen)
|
||||
{
|
||||
maxlen = usb_ep_out_get_data_long(pbuf, maxlen);
|
||||
usb_control_acknowledge();
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* TODO: Combine the functions */
|
||||
@@ -0,0 +1,137 @@
|
||||
/****************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_H__
|
||||
#define __USB_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb_config.h"
|
||||
|
||||
/* public interface to virtual USB peripheral & Stack */
|
||||
|
||||
/* some definitions for USB descriptors */
|
||||
#define DESCRIPTOR_DEVICE (0x01) /* Get device descriptor: Device */
|
||||
#define DESCRIPTOR_CONFIGURATION (0x02) /* Get device descriptor: Configuration */
|
||||
#define DESCRIPTOR_STRING (0x03) /* Get device descriptor: String */
|
||||
#define DESCRIPTOR_INTERFACE (0x04)
|
||||
#define DESCRIPTOR_ENDPOINT (0x05)
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
#define DESCRIPTOR_HID (0x21) /* Get descriptor: HID */
|
||||
#define DESCRIPTOR_REPORT (0x22) /* Get descriptor: Report */
|
||||
#endif
|
||||
|
||||
#define EPTYPE_CONTROL (0x00)
|
||||
#define EPTYPE_INTERRUPT (0x03)
|
||||
|
||||
|
||||
/* Some defines for endpoint function parameters => TODO, will be used in a later stage */
|
||||
#define USB_EPSETUP (0)
|
||||
#define USB_EP0OUT (16)
|
||||
#define USB_EP0IN (32)
|
||||
#if USB_ENABLE_EP1OUT_EP1IN == 1
|
||||
#define USB_EP1OUT (48)
|
||||
#define USB_EP1IN (64)
|
||||
#endif
|
||||
|
||||
|
||||
/* struct, which is used for control transfers */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wLength;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
} setupData_t;
|
||||
|
||||
|
||||
|
||||
/* Initialize USB and all used peripherals
|
||||
It startes with the USB peripheral disconnected from PC.
|
||||
Call usb_connect after initialization.
|
||||
*/
|
||||
void usb_init(void);
|
||||
|
||||
void usb_connect(void);
|
||||
|
||||
void usb_disconnect(void);
|
||||
|
||||
bool usb_check_resetcondition(void);
|
||||
|
||||
void usb_reset_received(void);
|
||||
|
||||
|
||||
|
||||
/* check, if a setup packet was received */
|
||||
bool usb_setup_available(void);
|
||||
|
||||
/* read setup data. Setup data does have a fixed length of 8 Bytes */
|
||||
void usb_setup_get_data(setupData_t *psetupdata);
|
||||
|
||||
|
||||
|
||||
/* check, if data can be written to ep0in buffer (== buffer is empty) */
|
||||
bool usb_ep_in_buf_empty(uint32_t epnum);
|
||||
|
||||
|
||||
/* write data to ep0in buffer */
|
||||
void usb_ep_in_commit_pkt(uint32_t epnum, bool firstpkt, const uint8_t *pbuf, uint32_t len);
|
||||
|
||||
|
||||
|
||||
/* check, if received data is in OUT endpoint */
|
||||
bool usb_ep_out_data_available(uint32_t epnum);
|
||||
|
||||
/* get data from EPxOUT. Length [bytes] is returned. */
|
||||
uint32_t usb_ep_out_get_data(uint32_t epnum, uint8_t *pbuf);
|
||||
|
||||
/* stall endpoint */
|
||||
void usb_ep_stall(uint32_t epnum);
|
||||
|
||||
/* remove stall condition from endpoint */
|
||||
void usb_ep_unstall(uint32_t epnum);
|
||||
|
||||
/* returns true if endpoint is stalled */
|
||||
bool usb_ep_is_stalled(uint32_t epnum);
|
||||
|
||||
/* receive a package via EP0OUT. It is allowed to be longer than 8 bytes */
|
||||
/* important: ensure, that pbuf has a buffer size with a multiple of 8 Bytes */
|
||||
/* returns received length */
|
||||
uint8_t usb_ep_out_get_data_long(uint8_t *pbuf, uint8_t maxlen);
|
||||
|
||||
/* send a package via EP0IN which is longer as 7 bytes */
|
||||
//void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len);
|
||||
void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len, bool sendshortpkt);
|
||||
|
||||
|
||||
|
||||
/* Handle a Control transfer without data stage => transmits a ACK in status stage */
|
||||
void usb_control_acknowledge(void);
|
||||
|
||||
/* Handle a Control IN transfer */
|
||||
bool usb_control_dataIn(const uint8_t *pbuf, uint8_t len);
|
||||
|
||||
/* Handle a Control OUT transfer */
|
||||
uint8_t usb_control_dataOut(uint8_t *pbuf, uint8_t maxlen);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_CONFIG_H__
|
||||
#define __USB_CONFIG_H__
|
||||
|
||||
/* Set to 1 to enable 2 additional endpoints.
|
||||
If set to 0, only control transfers will be supported, because only EP0OUT and EP0IN are present
|
||||
*/
|
||||
#define USB_ENABLE_EP1OUT_EP1IN (1)
|
||||
|
||||
#define USB_ENABLE_HID
|
||||
|
||||
/*
|
||||
Enable this define, if the USB low level protocol handling should be done in RAM.
|
||||
This is e.g. mandatory if Flash programming is used, otherwise USB will not be
|
||||
responsive anymore when flash is erased or programmed, because Flash accesses will
|
||||
be stalled.
|
||||
*/
|
||||
#define USB_PROTOCOL_HANDLING_IN_RAM
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_DESCRIPTORS_H__
|
||||
#define __USB_DESCRIPTORS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb.h"
|
||||
|
||||
/* include this file only once! */
|
||||
|
||||
#define WBVAL(x) (x & 0xFF),((x >> 8) & 0xFF)
|
||||
|
||||
|
||||
/* report descriptor for HID keyboard */
|
||||
const uint8_t hid_report_descriptor[] =
|
||||
{
|
||||
0x05, 0x01, 0x09,
|
||||
0x06, 0xA1,
|
||||
0x01, 0x05,
|
||||
0x07, 0x19,
|
||||
0xE0, 0x29, 0xE7,
|
||||
0x15, 0x00,
|
||||
0x25, 0x01,
|
||||
0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01,
|
||||
0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01,
|
||||
0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02,
|
||||
0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06,
|
||||
0x75, 0x08, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x05,
|
||||
0x07, 0x19, 0x00, 0x2A, 0xFF, 0x00, 0x81, 0x00,
|
||||
0xC0
|
||||
};
|
||||
|
||||
|
||||
const uint8_t device_descriptor[] =
|
||||
{
|
||||
0x12, /* descriptor length */
|
||||
0x01, /* descriptor type */
|
||||
WBVAL(0x0110), /* USB version */
|
||||
0x00, /* Devices class */
|
||||
0x00, /* Device sub class */
|
||||
0x00, /* Device sub sub class */
|
||||
0x08, /* max packet size (for EP0IN/OUT) */
|
||||
WBVAL(0x10C4), /* VID (low, high) */
|
||||
WBVAL(0x8944), /* PID */
|
||||
WBVAL(0x0100), /* DID */
|
||||
0x01, /* manufacturer string index */
|
||||
0x02, /* product string index */
|
||||
0x00, /* serial number string index */
|
||||
0x01 /* number of configurations */
|
||||
};
|
||||
|
||||
const uint8_t config_0_descriptor[] =
|
||||
{
|
||||
0x09, /* length of config descriptor */
|
||||
DESCRIPTOR_CONFIGURATION, /* descriptor type */
|
||||
0x12+7+9, 0x00, /* Config + Interface + Endpoints length (low, high) */
|
||||
0x01, /* number of interfaces */
|
||||
0x01, /* interface number */
|
||||
0x00, /* configuration string index */
|
||||
0xA0, /* attributes (buspowered = Bit7, Selfpowered = Bit6, RemoteWakeup = Bit 5) */
|
||||
50, /* power requirement (multiply by 2 to get current in mA) */
|
||||
|
||||
/* interface descriptor */
|
||||
0x09, /* length of interface descriptor */
|
||||
DESCRIPTOR_INTERFACE, /* descriptor type */
|
||||
0x00, /* Index of this interface (starts at 0) */
|
||||
0x00, /* Alternate setting */
|
||||
0x01, /* Number of Endpoints */
|
||||
0x03, /* Interface class */
|
||||
0x01, /* Interface sub class */
|
||||
0x01, /* Interface sub sub class */
|
||||
0x00, /* Interface descriptor string index */
|
||||
|
||||
/* HID descriptor - Keyboard */
|
||||
0x09, /* Length of this descriptor */
|
||||
DESCRIPTOR_HID, /* bDescriptorType */
|
||||
WBVAL(0x0100), /* 1.00 */ /* bcdHID */
|
||||
0x00, /* bCountryCode */
|
||||
0x01, /* bNumDescriptors */
|
||||
0x22, /* bDescriptorType */
|
||||
WBVAL(sizeof(hid_report_descriptor)), /* wDescriptorLength */
|
||||
|
||||
/* EP1IN */
|
||||
0x07, /* length of endpoint descriptor */
|
||||
DESCRIPTOR_ENDPOINT, /* descriptor type */
|
||||
0x81, /* Endpoint number and direction (Bit 7) */
|
||||
EPTYPE_INTERRUPT, /* Endpoint type */
|
||||
0x08, 0x00, /* Max packet size of this Endpoint (Low, High) */
|
||||
0x18 /* Polling Interval */
|
||||
};
|
||||
|
||||
const uint8_t string_0_descriptor[] =
|
||||
{
|
||||
0x04, /* length of string descriptor */
|
||||
DESCRIPTOR_STRING, /* descriptor type */
|
||||
0x09,
|
||||
0x04
|
||||
};
|
||||
|
||||
const uint8_t string_1_descriptor[] =
|
||||
{
|
||||
0x14, /* length of string descriptor */
|
||||
DESCRIPTOR_STRING, /* descriptor type */
|
||||
'L', 0,
|
||||
'E', 0,
|
||||
'M', 0,
|
||||
'C', 0,
|
||||
'U', 0,
|
||||
'.', 0,
|
||||
'O', 0,
|
||||
'R', 0,
|
||||
'G', 0,
|
||||
};
|
||||
|
||||
const uint8_t string_2_descriptor[] =
|
||||
{
|
||||
0x1A, /* length of string descriptor */
|
||||
DESCRIPTOR_STRING, /* descriptor type */
|
||||
'I', 0,
|
||||
't', 0,
|
||||
' ', 0,
|
||||
'w', 0,
|
||||
'o', 0,
|
||||
'r', 0,
|
||||
'k', 0,
|
||||
's', 0,
|
||||
' ', 0,
|
||||
':', 0,
|
||||
'-', 0,
|
||||
')', 0,
|
||||
};
|
||||
|
||||
const uint8_t hid_descriptor[] =
|
||||
{
|
||||
0x09,
|
||||
DESCRIPTOR_HID,
|
||||
0x10, 0x01, /* USB version */
|
||||
0x00, /* Localization*/
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_HELPERFUNCTIONS_H__
|
||||
#define __USB_HELPERFUNCTIONS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* from bit twiddling hacks. Did not check efficiency.
|
||||
My guess is, that the standard assembly way using 8 consecutive ROR/ROL instructions is faster!
|
||||
so: TODO check and optimize
|
||||
*/
|
||||
static inline uint8_t bitreverse(uint8_t b)
|
||||
{
|
||||
return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Make this nice and efficient! Maybe implement this directly in CM0+ assembly
|
||||
using uint32_t instead of uint8_t can also speed things up
|
||||
See: http%3A%2F%2Fwww.usb.org%2Fdevelopers%2Fwhitepapers%2Fcrcdes.pdf&ei=
|
||||
AKrAUtuBD4WMtQakyoCwAQ&usg=AFQjCNE71tY6EAUjJKXWbjtbNvDTiOKKlg&bvm=bv.
|
||||
58187178,d.Yms&cad=rja
|
||||
*/
|
||||
static uint16_t crc16(uint16_t crc, uint8_t c)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
if ((crc ^ c) & 1)
|
||||
{
|
||||
crc = (crc >> 1) ^ 0xa001; /* 0xa001*/
|
||||
}
|
||||
else
|
||||
{
|
||||
crc >>= 1;
|
||||
}
|
||||
c >>= 1;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "usb_stack.h"
|
||||
#include "usb.h"
|
||||
#include "usb_helperfunctions.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb_hid.h"
|
||||
|
||||
//#include "em_device.h" /* removeme. Only needed for debugging */
|
||||
|
||||
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
|
||||
/* HID requests */
|
||||
#define HID_GET_REPORT (0x01) /* mandatory */
|
||||
#define HID_GET_IDLE (0x02) /* optional */
|
||||
#define HID_GET_PROTOCOL (0x03) /* mandatory for BOOT devices */
|
||||
#define HID_SET_REPORT (0x09) /* mandatory if USB device does not use EP1OUT */
|
||||
#define HID_SET_IDLE (0x0a) /* optional */
|
||||
#define HID_SET_PROTOCOL (0x0b) /* mandatory for BOOT devices */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool usbhid_got_setup_cmd(const setupData_t *psetupdata)
|
||||
{
|
||||
uint8_t response[8];
|
||||
bool doStall;
|
||||
|
||||
doStall = false;
|
||||
|
||||
switch(psetupdata->bRequest)
|
||||
{
|
||||
case HID_GET_REPORT:
|
||||
doStall = !HID_GetReport(psetupdata->wValue >> 8);
|
||||
break;
|
||||
case HID_SET_REPORT:
|
||||
doStall = !HID_SetReport(psetupdata->wValue >> 8);
|
||||
if (!doStall)
|
||||
{
|
||||
//usb_control_acknowledge(); //TODO: REMOVE UNCOMMENT!!!
|
||||
}
|
||||
break;
|
||||
case HID_GET_PROTOCOL:
|
||||
doStall = !HID_GetProtocol(response);
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_dataIn(response, 1);
|
||||
}
|
||||
break;
|
||||
case HID_SET_PROTOCOL:
|
||||
doStall = !HID_SetProtocol(psetupdata->wValue >> 8); /* low byte of value is interface number */
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_acknowledge();
|
||||
}
|
||||
break;
|
||||
case HID_GET_IDLE:
|
||||
doStall = !HID_GetIdle(response);
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_dataIn(response, 1);
|
||||
}
|
||||
break;
|
||||
case HID_SET_IDLE:
|
||||
doStall = !HID_SetIdle(psetupdata->wValue >> 8); /* low byte of value is interface number */
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_acknowledge();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (doStall)
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_HID_H__
|
||||
#define __USB_HID_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
|
||||
|
||||
/* HID Report Types */
|
||||
#define HID_RPRT_INPUT (0x01)
|
||||
#define HID_RPRT_OUTPUT (0x02)
|
||||
#define HID_RPRT_FEATURE (0x03)
|
||||
|
||||
|
||||
/* HID Requests functions, need to be defined by the user! */
|
||||
/* They are not implemented as callback functions to get */
|
||||
/* a more efficient code.*/
|
||||
/* The functions should false, if they were not handled */
|
||||
/* return TRUE if function was handled */
|
||||
extern bool HID_GetReport (uint8_t reportType);
|
||||
extern bool HID_SetReport (uint8_t reportType);
|
||||
extern bool HID_GetIdle (uint8_t *pIdleTime);
|
||||
extern bool HID_SetIdle (uint8_t idleTime);
|
||||
extern bool HID_GetProtocol (uint8_t *pProtocol);
|
||||
extern bool HID_SetProtocol (uint8_t protocol);
|
||||
|
||||
|
||||
|
||||
bool usbhid_got_setup_cmd(const setupData_t *psetupdata);
|
||||
|
||||
|
||||
|
||||
#else
|
||||
#warning "HID disabled, but hid includes compiled"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,484 @@
|
||||
//****************************************************************************
|
||||
//
|
||||
// Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
// Copyright (C) 2014 http://lemcu.org
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3.0 as
|
||||
// published by the Free Software Foundation and appearing in the file
|
||||
// LICENSE.txt included in the packaging of this file.
|
||||
//
|
||||
// In addition, as a special exception, http://lemcu.org gives you certain
|
||||
// additional rights. These rights are described in the lemcu.org GPL
|
||||
// Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
// package.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY// without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
//**************************************************************************/
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
NAME usb_internal_bitbangusb
|
||||
|
||||
;; For a description of the purpose of the following part, look here:
|
||||
;; http://supp.iar.com/Support/?note=80737&from=search+result
|
||||
;; (TOPIC: IAR assembler ramfunction)
|
||||
#define SHT_PROGBITS 0x1
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_EXECINSTR 0x4
|
||||
RSEG MYCODE:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
||||
THUMB
|
||||
EXTERN usb_protocol_handle
|
||||
|
||||
PUBLIC GPIO_ODD_IRQHandler
|
||||
PUBLIC usb_transmit
|
||||
PUBLIC protocol_handled
|
||||
#else
|
||||
.syntax unified
|
||||
.arch armv6-m
|
||||
|
||||
.SECTION .functioninRAM
|
||||
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
.extern usb_protocol_handle
|
||||
|
||||
|
||||
|
||||
.global GPIO_ODD_IRQHandler
|
||||
.global usb_transmit
|
||||
.global protocol_handled
|
||||
|
||||
|
||||
.type GPIO_ODD_IRQHandler, %function // IMPORTANT FOR GCC to get lsb of address set to 1
|
||||
.type protocol_handled, %function // IMPORTANT FOR GCC to get lsb of address set to 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#define USBEP_OFS_SETUP ( 0)
|
||||
#define USBEP_OFS_EP0OUT (16)
|
||||
#define USBEP_OFS_EP0IN (32)
|
||||
#define USBEP_OFS_EP1OUT (48)
|
||||
#define USBEP_OFS_EP1IN (64)
|
||||
|
||||
#define USBEP_SOFS_STAT (12)
|
||||
#define USBEP_SOFS_LEN (13)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// This is the Interrupt handler, triggered by a rising edge on D+ (PC1)
|
||||
// It is implemented in assembly to minimize latency
|
||||
// (=> avoid branch from C code to ASM and addition of veneer code)
|
||||
|
||||
// This is called for each received USB data packet. received data is unstuffed.
|
||||
// The data is decoded to R8, R9, R10
|
||||
// Each data byte is in reversed bitorder. For data bytes, the bitorder
|
||||
// needs to be reversed. For PIDs, etc. bitorder reversal is not mandatory
|
||||
// The received bitcount is written to R11
|
||||
// BYTE ORDER:
|
||||
// R8. 24-31 Byte 0
|
||||
// R8. 16-23 Byte 1
|
||||
// R8. 8-15 Byte 2
|
||||
// R8. 0- 7 Byte 3
|
||||
// R9. 24-31 Byte 4
|
||||
// R9. 16-23 Byte 5
|
||||
// R9. 8-15 Byte 6
|
||||
// R9. 0- 7 Byte 7
|
||||
// R10.24-31 Byte 8
|
||||
// R10.16-23 Byte 9
|
||||
// R10. 8-15 Byte 10
|
||||
// R10. 0- 7 Byte 11
|
||||
//
|
||||
// An interupt saves the following register on stack:
|
||||
// - R0-R3, R12
|
||||
// - LR, PC & xPSR
|
||||
GPIO_ODD_IRQHandler:
|
||||
|
||||
NOP
|
||||
NOP
|
||||
|
||||
MOV r0, r8
|
||||
MOV r1, r9
|
||||
MOV r2, r10
|
||||
MOV r3, r11
|
||||
PUSH {r0-r7}
|
||||
MOV r0, LR
|
||||
PUSH {r0}
|
||||
|
||||
|
||||
MOVS r3, #3
|
||||
MOVS r4, #0xff // preload with 0xff to avoid bitunstuffing after start
|
||||
MOVS r5, #0x80
|
||||
LSLS r5, r5, #24
|
||||
MOVS r0, #0
|
||||
MOV r11, r0
|
||||
MOVS r1, #1
|
||||
MOV r12, r1
|
||||
|
||||
// r1 = 1
|
||||
// r3 = 3
|
||||
// r5 = (1<<13)
|
||||
// r7 = &GPIO_PE_DOUTSET
|
||||
|
||||
LDR r7, GPIO_PC_DIN // r7 = address of register GPIO_PC_DIN
|
||||
|
||||
// wait until a 1 is detected. Unfolded loop to be able to detect a timeout condition
|
||||
usb_sync_wait_while_0:
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
|
||||
B protocol_handled // State was zero for more than 1 bittime => exit (timeout condition)
|
||||
|
||||
|
||||
usb_sync_found:
|
||||
// delay 1 bittime
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
NOP
|
||||
|
||||
// check, if bitstate is still 1 (=> if 2 consecutive 1 bits received)
|
||||
LDR r2, [r7] // read port state
|
||||
TST r2, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
|
||||
BL _delay_13
|
||||
|
||||
// here: We are in the middle of the very first bit of this packet
|
||||
// r0 = port state current
|
||||
// r1 = 1
|
||||
// r2 = port state old
|
||||
// r3 = 3
|
||||
// r4/5/6 = received data (parallel)
|
||||
// r7 = address of GPIO_PC_DIN
|
||||
// r11 = bitcounter
|
||||
MOVS r1, #0
|
||||
|
||||
rcv_bits: LDR r0, [r7] // read port state
|
||||
ANDS r0, r3 // check for SE0 and mask out unneeded bits
|
||||
BEQ se0_detected // end of receive loop!
|
||||
EORS r2, r0 // NRZ decoding (XOR bitstate with old bitstate) => inverts data, USB uses NRZI!
|
||||
LSRS r2, r2, #1
|
||||
ADCS r4, r4, r4 // Shift carry into receive chain
|
||||
ADCS r5, r5, r5
|
||||
ADCS r6, r6, r6
|
||||
ADD r11, r11, r12 // increment bitcounter
|
||||
MOV r2, r0 // Store old bitstate
|
||||
NOP
|
||||
LSLS r1, r1, #1 // Shift bitunstuffing EOR mask
|
||||
LSLS r0, r4, #26 // Mask out last 6 received bits
|
||||
EORS r0, r0, r1 // check if 6 consecutive 0s have been received
|
||||
BNE rcv_bits
|
||||
|
||||
// here we get when bitunstuffing needs to be done
|
||||
// 15/16 cycles over
|
||||
NOP //16
|
||||
LDR r2, [r7] // 1 // read port state to save it as "old" bitstate
|
||||
BL _delay_11 //12
|
||||
MOVS r1, #1 //13 // save bitunstuffing EOR mask
|
||||
LSLS r1, r1, #26 //14
|
||||
B rcv_bits //16
|
||||
|
||||
|
||||
|
||||
|
||||
se0_detected:
|
||||
// left align data (rough: 32 Bit steps)
|
||||
MOV r0, r11
|
||||
CMP r0, #64
|
||||
BHI se0_detected_align_0
|
||||
|
||||
MOVS r6, r5
|
||||
MOVS r5, r4
|
||||
SUBS r4, r4, r4 // not mandatory
|
||||
|
||||
CMP r0, #32
|
||||
BHI se0_detected_align_0
|
||||
|
||||
MOVS r6, r5
|
||||
MOVS r5, r4
|
||||
SUBS r4, r4, r4 // not mandatory
|
||||
|
||||
// left align data (fine alignment: 0..31 bits)
|
||||
se0_detected_align_0: MOV r0, r11
|
||||
MOVS r1, #31
|
||||
ANDS r1, r1, r0 // r1 = bitcount & 31
|
||||
|
||||
CMP r1, #0
|
||||
BEQ se0_alginment_done
|
||||
|
||||
MOVS r0, #0
|
||||
MVNS r0, r0 // r0 = 0xffffffff
|
||||
LSRS r0, r0, r1 // 8 => 0x00ffffff, 24 => 0x000000ff r0 = Mask of bytes to copy from lower word to upper one
|
||||
|
||||
RORS r6, r6, r1 //
|
||||
BICS r6, r6, r0 // r6 = r6 and not r0 (reset lower bytes to 0)
|
||||
|
||||
RORS r5, r5, r1 //
|
||||
MOVS r2, r5
|
||||
ANDS r2, r2, r0
|
||||
ORRS r6, r6, r2 //
|
||||
BICS r5, r5, r0 // r6 = r6 and not r0 (reset lower bytes to 0)
|
||||
|
||||
RORS r4, r4, r1 //
|
||||
MOVS r2, r4
|
||||
ANDS r2, r2, r0
|
||||
ORRS r5, r5, r2
|
||||
BICS r4, r4, r0 // not mandatory
|
||||
|
||||
|
||||
|
||||
// Invert data (NRZ => NRZI)
|
||||
se0_alginment_done: MVNS r0, r4
|
||||
MOV r10, r0
|
||||
MVNS r0, r5
|
||||
MOV r9, r0
|
||||
MVNS r0, r6
|
||||
MOV r8, r0
|
||||
|
||||
LDR r0, LABEL_USB_PROT_HDL
|
||||
BX r0 // Jump to protocol state machine code located in Flash
|
||||
|
||||
|
||||
protocol_handled:
|
||||
// This was for debugging. enable it, if you want to debug host packets only
|
||||
// MOVS r5, #255
|
||||
//delayloop:
|
||||
// SUBS r5, r5, #1
|
||||
// BNE delayloop
|
||||
|
||||
// acknowledge GPIO interrupt
|
||||
LDR r6, GPIO_IFC
|
||||
MOVS r5, #2
|
||||
STR r5, [r6]
|
||||
|
||||
POP {r0}
|
||||
MOV LR, r0
|
||||
|
||||
POP {r0-r7}
|
||||
MOV r8, r0
|
||||
MOV r9, r1
|
||||
MOV r10, r2
|
||||
MOV r11, r3 // r0-r3 are restored by ISR return
|
||||
BX LR // return
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
DATA
|
||||
ALIGNROM 2
|
||||
GPIO_PC_DIN: DC32 0x40006064 ; GPIO_PC_DIN
|
||||
GPIO_PE_DOUTSET DC32 0x400060a0 ; GPIO_PE_DOUTSET.DOUTSET
|
||||
GPIO_IFC: DC32 0x4000611c ; GPIO.IFC
|
||||
LABEL_USB_PROT_HDL: DC32 usb_protocol_handle
|
||||
//GPIO_PB_TOGGLE: DC32 0x4000603C ; REMOVEME
|
||||
|
||||
#else
|
||||
.BALIGN 4
|
||||
GPIO_PC_DIN: .INT 0x40006064 // GPIO_PC_DIN
|
||||
GPIO_PE_DOUTSET: .INT 0x400060a0 // GPIO_PE_DOUTSET.DOUTSET
|
||||
GPIO_IFC: .INT 0x4000611c // GPIO.IFC
|
||||
LABEL_USB_PROT_HDL: .INT usb_protocol_handle
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
CODE
|
||||
THUMB
|
||||
#else
|
||||
.SECTION .functioninRAM
|
||||
.THUMB
|
||||
#endif
|
||||
// This function transmits a USB packet as response to the host
|
||||
// Used for : ACK, NAK, STALL, DATA0 & DATA1 PIDs
|
||||
// Parameters:
|
||||
// r0/r1/r2 = Data to transmit
|
||||
// r5 = Bitcount
|
||||
// The Bitorder of the transmission is the right one (no bitreversal as in receive function)
|
||||
// transmit order:
|
||||
// r0.0-7 => r0.8-15 => r0.16-23 => r0.24-31 =>
|
||||
// r1.0-7 => r1.8-15 => r1.16-23 => r1.24-31 =>
|
||||
// r2.0-7 => r2.8-15 => r2.16-23 => r2.24-31
|
||||
usb_transmit:
|
||||
MOV r7, LR
|
||||
PUSH {r7}
|
||||
// Switch PC0 & PC1 to output
|
||||
LDR r7, GPIO_PC_BASE
|
||||
LDR r3, [r7, #4] // read pin mode low register
|
||||
ADDS r3, r3, #0x33 // mode Input = 0x11, Output = 0x44
|
||||
STR r3, [r7, #4] // writepin mode low register
|
||||
// IO state = push pull & IDLE (D-=1 D+=0)
|
||||
|
||||
// 1.) Send SYNC Byte
|
||||
MOVS r3, #0x03 // bitmask for toggling IO pin
|
||||
MOVS r4, #7
|
||||
usb_tx_syncloop: STR r3, [r7, #24] // Toggle IOs to transmit a 0
|
||||
BL _delay_12
|
||||
SUBS r4, r4, #1
|
||||
BNE usb_tx_syncloop
|
||||
//15
|
||||
// transmit a "1" - last bit of SYNC sequence
|
||||
BL _delay_12
|
||||
|
||||
// 2.) Send data given in registers r0/r1/r2 and bitcount in r5
|
||||
// Here all bits get transmitted. Bitstuffing is also applied
|
||||
// The minimal version of this would only need 6 cycles
|
||||
MOVS r4, #5 // consecutive 1-Bit counter (used for bitstuffing). Last transmitted Bit was 1, so initialize it with 5 rather than 6
|
||||
MOVS r6, #32 // Needed to check if a new 32 Bit word should be transmitted
|
||||
usb_tx_bitloop: LSRS r0, r0, #1 // shift out bit to carry flag for transmitting
|
||||
BCS usb_txbitloop_send1 //do nothing if bit is 1 (only a zero causes toggling
|
||||
usb_txbitloop_send0: STR r3, [r7, #24] // Toggle IOs to transmit a 0
|
||||
MOVS r4, #6 // Reset 1-Bit counter
|
||||
B usb_txbitloop_sent1
|
||||
usb_txbitloop_send1: SUBS r4, #1
|
||||
BEQ usb_tx_sendstuffbit
|
||||
usb_tx_bitstutt_ret: NOP // equalize execution time for 2 branch paths
|
||||
usb_txbitloop_sent1: SUBS r5, r5, #1
|
||||
BEQ usb_tx_send_eop // final word transmitted
|
||||
SUBS r6, r6, #1
|
||||
BEQ usb_txbit_nextword
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
B usb_tx_bitloop
|
||||
|
||||
// select next word for transmission
|
||||
usb_txbit_nextword: MOVS r0, r1
|
||||
MOVS r1, r2
|
||||
MOVS r6, #32
|
||||
B usb_tx_bitloop
|
||||
|
||||
// Send stuffbit
|
||||
// 4 cycles over since last bit
|
||||
usb_tx_sendstuffbit: BL _delay_11
|
||||
MOVS r4, #6 // Reset 1-Bit counter
|
||||
STR r3, [r7, #24] // Toggle IOs to transmit a 0
|
||||
B usb_tx_bitstutt_ret
|
||||
|
||||
// send EOP (2*SE0)
|
||||
// 7 cycles over since last bit
|
||||
usb_tx_send_eop:
|
||||
BL _delay_9
|
||||
STR r3, [r7, #20] // write to GPIO_PC_DOUTCLR to set D+ and D- to LOW
|
||||
BL _delay_10
|
||||
BL _delay_10
|
||||
BL _delay_10
|
||||
|
||||
MOVS r1, #1
|
||||
STR r1, [r7, #16] // Set D- back to HIGH
|
||||
|
||||
// Switch PC0 & PC1 to input
|
||||
LDR r7, GPIO_PC_BASE
|
||||
LDR r0, [r7, #4] // read pin mode low register
|
||||
SUBS r0, r0, #0x33 // set from 0x44 to 0x11 (push pull to input)
|
||||
STR r0, [r7, #4] // writepin mode low register
|
||||
|
||||
// // delay some time for easier debugging
|
||||
// MOVS r5, #255
|
||||
//delayloop_x: MOVS r4, #6 // reset 1-bit counter
|
||||
// SUBS r5, r5, #1
|
||||
// BNE delayloop_x
|
||||
POP {r0}
|
||||
MOV LR, r0
|
||||
BX LR
|
||||
|
||||
// some delay functions:
|
||||
_delay_14: NOP
|
||||
_delay_13: NOP
|
||||
_delay_12: NOP
|
||||
_delay_11: NOP
|
||||
_delay_10: NOP
|
||||
_delay_9: NOP
|
||||
_delay_8: NOP
|
||||
_delay_7: NOP
|
||||
_delay_6: NOP
|
||||
_delay_5: BX LR
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
|
||||
DATA
|
||||
ALIGNROM 2
|
||||
GPIO_PC_BASE: DC32 0x40006048 ; GPIO_PC_DIN - This is redundant, has already been defined in the RX function
|
||||
GPIO_PE_DOUTSET_ DC32 0x400060a0 ; GPIO_PE_DOUTSET.DOUTSET
|
||||
|
||||
END
|
||||
|
||||
#else
|
||||
|
||||
.BALIGN 4
|
||||
GPIO_PC_BASE: .INT 0x40006048 // GPIO_PC_DIN - This is redundant, has already been defined in the RX function
|
||||
GPIO_PE_DOUTSET_: .INT 0x400060a0 // GPIO_PE_DOUTSET.DOUTSET
|
||||
|
||||
.END
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
TODO:
|
||||
- Flag endpoint status based on Host reply
|
||||
- interpret CRC5 ??
|
||||
- detect RESET condition on bus (very long SE0 phase, check USB spec. for duration). This should reset the usb address
|
||||
- RESET = SE0 for >= 10ms
|
||||
|
||||
- codesize optimization:
|
||||
* use branches to identical code secitions
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Low level internal functions.
|
||||
* These functions are internal.
|
||||
*/
|
||||
|
||||
//#include "em_device.h"
|
||||
#include <stdint.h>
|
||||
//#include "em_chip.h"
|
||||
//#include "em_int.h"
|
||||
#include "gpio.h"
|
||||
//#include "em_cmu.h"
|
||||
|
||||
#include "usb_config.h"
|
||||
|
||||
/* Endpoint buffers
|
||||
Offset 0: SETUP packets
|
||||
Offset 16: EP0OUT
|
||||
Offset 32: EP0IN
|
||||
(Offset 48: EP1OUT)
|
||||
(Offset 64: EP1IN)
|
||||
|
||||
Offsets within one of theese buffers:
|
||||
0-11: Raw data
|
||||
Offset 12: _STAT Status empty/filled (0x00/0x01)
|
||||
Offset 13: _LEN Length of data in buffer
|
||||
14 & 15 are free for future used - would be added anyway by codegen tools for alignment
|
||||
*/
|
||||
volatile uint8_t usb_ep_buffers[ (3+2*USB_ENABLE_EP1OUT_EP1IN)*16 ];
|
||||
|
||||
/* low level protocol handling state */
|
||||
/* Bit 0- 7 = state machine index*/
|
||||
/* Bit 8-15 = last received USB Address (bitreversed: a0 a1 a2 a3 a4 a5 a6 0) */
|
||||
/* Bit 16-23 = last received USB Endpoint (bitreversed: e0 e1 e2 e3 0 0 0 0) */
|
||||
/* Bit 24-31 = not used yet */
|
||||
uint32_t USB_PROT_STATE;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_INTERNAL_H__
|
||||
#define __USB_INTERNAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb_config.h"
|
||||
|
||||
#define USB_EPBUF_OFFSET_SETUP_BUF ( 0)
|
||||
#define USB_EPBUF_OFFSET_EP0OUT_BUF (16)
|
||||
#define USB_EPBUF_OFFSET_EP0IN_BUF (32)
|
||||
#define USB_EPBUF_OFFSET_EP1OUT_BUF (48)
|
||||
#define USB_EPBUF_OFFSET_EP1IN_BUF (64)
|
||||
|
||||
#define USB_EPBUF_SUBOFFSET_STAT (12)
|
||||
#define USB_EPBUF_SUBOFFSET_LEN (13)
|
||||
|
||||
|
||||
/* Endpoint buffers
|
||||
Offset 0: SETUP packets
|
||||
Offset 16: EP0OUT
|
||||
Offset 32: EP0IN
|
||||
(Offset 48: EP1OUT)
|
||||
(Offset 64: EP1IN)
|
||||
|
||||
Sub-offsets within one of these buffers:
|
||||
0-11: Raw data
|
||||
Offset 12: _STAT Status empty/filled (0x00/0x01)
|
||||
Offset 13: _LEN Length of data in buffer
|
||||
14 & 15 are free for future used - would be added anyway by codegen tools for alignment
|
||||
*/
|
||||
|
||||
|
||||
/* Endpoint buffers */
|
||||
extern volatile uint8_t usb_ep_buffers[ (3+2*USB_ENABLE_EP1OUT_EP1IN)*16 ];
|
||||
|
||||
extern uint32_t USB_PROT_STATE;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,329 @@
|
||||
#include "usb_config.h"
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
NAME usb_internal_prot_handling
|
||||
#ifdef USB_PROTOCOL_HANDLING_IN_RAM
|
||||
#define SHT_PROGBITS 0x1
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_EXECINSTR 0x4
|
||||
RSEG MYCODE:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
||||
THUMB
|
||||
#else
|
||||
section CODE:CODE (2)
|
||||
CODE
|
||||
#endif
|
||||
|
||||
THUMB
|
||||
|
||||
EXTERN usb_dev_address
|
||||
EXTERN USB_PROT_STATE
|
||||
EXTERN usb_ep_buffers
|
||||
EXTERN protocol_handled
|
||||
EXTERN usb_transmit
|
||||
|
||||
|
||||
PUBLIC usb_protocol_handle
|
||||
#else
|
||||
.syntax unified
|
||||
.arch armv6-m
|
||||
#ifdef USB_PROTOCOL_HANDLING_IN_RAM
|
||||
.THUMB
|
||||
.section .functioninRAM
|
||||
#else
|
||||
.BALIGN 4
|
||||
.TEXT
|
||||
#endif
|
||||
.THUMB
|
||||
|
||||
.EXTERN usb_dev_address
|
||||
.EXTERN USB_PROT_STATE
|
||||
.EXTERN usb_ep_buffers
|
||||
.EXTERN protocol_handled
|
||||
.EXTERN usb_transmit
|
||||
|
||||
|
||||
.GLOBAL usb_protocol_handle
|
||||
|
||||
.type usb_protocol_handle, %function // IMPORTANT FOR GCC to get lsb of address set to 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Endpoint buffer offsets and suboffsets*/
|
||||
#define USBEP_OFS_SETUP ( 0)
|
||||
#define USBEP_OFS_EP0OUT (16)
|
||||
#define USBEP_OFS_EP0IN (32)
|
||||
#define USBEP_OFS_EP1OUT (48)
|
||||
#define USBEP_OFS_EP1IN (64)
|
||||
#define USBEP_SOFS_STAT (12)
|
||||
#define USBEP_SOFS_LEN (13)
|
||||
|
||||
|
||||
/* some internal C-Style MACROs */
|
||||
#define REV2(x) ((((x)&1)<<1) | (((x)>>1)&1))
|
||||
#define REV4(x) ((REV2(x)<<2) | (REV2((x)>>2)))
|
||||
#define REV8(x) ((REV4(x)<<4) | (REV4((x)>>4)))
|
||||
#define CREATE_PID(x) (x & 0x0F) | (((~x) & 0x0f)<<4)
|
||||
|
||||
/* define Bitreversed PIDs */
|
||||
#define USB_TOKEN_BR_OUT REV8(CREATE_PID( 0x01 ))
|
||||
#define USB_TOKEN_BR_IN REV8(CREATE_PID( 0x09 ))
|
||||
#define USB_TOKEN_BR_SETUP REV8(CREATE_PID( 0x0d ))
|
||||
#define USB_TOKEN_BR_DATA0 REV8(CREATE_PID( 0x03 ))
|
||||
#define USB_TOKEN_BR_DATA1 REV8(CREATE_PID( 0x0b ))
|
||||
#define USB_TOKEN_BR_ACK REV8(CREATE_PID( 0x02 ))
|
||||
#define USB_TOKEN_BR_NAK REV8(CREATE_PID( 0x0a ))
|
||||
|
||||
/* define PIDs used for transmit (not bitreversed) */
|
||||
#define USB_TOKEN_ACK CREATE_PID( 0x02 )
|
||||
#define USB_TOKEN_NAK CREATE_PID( 0x0a )
|
||||
#define USB_TOKEN_STALL CREATE_PID( 0x0e )
|
||||
|
||||
|
||||
|
||||
// The following registers are saved externally on stack:
|
||||
// r0-r11
|
||||
// Registers that are not allowed to be modified:
|
||||
// r12, LR
|
||||
|
||||
// Input data:
|
||||
// -----------
|
||||
// r11 = received bitcount
|
||||
// r8...r10 = received data
|
||||
//
|
||||
|
||||
// Output data:
|
||||
// ------------
|
||||
// none
|
||||
|
||||
// A complete packet was received.
|
||||
// Now do some protocol handling
|
||||
// 1.) Identify PID R8.24-31
|
||||
usb_protocol_handle:
|
||||
|
||||
LDR r7, ASM_USB_PROT_STATE // r7 = pointer to protocol state variable
|
||||
LDRB r6, [r7] // r6 = state machine state
|
||||
LDRB r5, [r7, #1] // r5 = Address from state variable
|
||||
LDRB r4, [r7, #2] // r4 = Endpoint from state variable
|
||||
LDR r3, ASM_USB_DEV_ADDRESS
|
||||
LDRB r3, [r3] // r3 = USB Addresss of this device
|
||||
MOV r0, r8
|
||||
LSRS r0, r0, #24 // r0 now contains the PID only
|
||||
CMP r0, #USB_TOKEN_BR_SETUP // sends address and endpoint as parameter
|
||||
BEQ pid_setup
|
||||
CMP r0, #USB_TOKEN_BR_DATA0
|
||||
BEQ pid_data0
|
||||
CMP r0, #USB_TOKEN_BR_DATA1
|
||||
BEQ pid_data1
|
||||
CMP r0, #USB_TOKEN_BR_IN // sends address and endpoint as parameter
|
||||
BEQ pid_in
|
||||
CMP r0, #USB_TOKEN_BR_OUT // sends address and endpoint as parameter
|
||||
BEQ pid_out
|
||||
|
||||
jump_exit: LDR r0, LBL_PROT_HANDLED
|
||||
BX r0
|
||||
|
||||
|
||||
|
||||
////////////// Protocol handling statemachine
|
||||
// r7 = pointer to protocol state variable
|
||||
// r6 = state machine state (Byte 0)
|
||||
// r5 = Address & endpoint from state variable (Byte 1)
|
||||
pid_setup: MOVS r0, #0
|
||||
STRB r0, [r7] // Flag, that the next data package is a setup packet
|
||||
MOV r0, r8
|
||||
// extract address
|
||||
LSRS r1, r0, #16
|
||||
MOVS r2, #0xfe
|
||||
ANDS r1, r1, r2 // Mask out address bits a0-a6. Order: a0 a1 a2 a3 a4 a5 a6 0
|
||||
STRB r1, [r7, #1] // Store address in protocol state
|
||||
|
||||
// extract endpoint number
|
||||
LSRS r1, r0, #9
|
||||
MOVS r2, #0xf0
|
||||
ANDS r1, r1, r2
|
||||
STRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
|
||||
B jump_exit
|
||||
|
||||
pid_data0:
|
||||
pid_data1:
|
||||
// Check the usb address
|
||||
CMP r5, r3
|
||||
BNE jump_exit // This device is not addressed => Don't react on DATA PID
|
||||
|
||||
CMP r6, #0 // check if this is data is a setup phase or out phase
|
||||
BEQ pid_data_setup
|
||||
|
||||
// Here: data PID is for OUT phase
|
||||
|
||||
// Create pointer to addressed endpoint buffer
|
||||
LDR r6, ASM_USB_EP_BUFFERS
|
||||
|
||||
LDRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
CMP r1, #0
|
||||
BEQ pid_da_ep0_addressed
|
||||
ADDS r6, r6, #USBEP_OFS_EP1OUT
|
||||
B pid_da_ep1_addressed
|
||||
pid_da_ep0_addressed: ADDS r6, r6, #USBEP_OFS_EP0OUT
|
||||
pid_da_ep1_addressed:
|
||||
|
||||
LDRB r0, [r6, #USBEP_SOFS_STAT]
|
||||
// check if endpoint is stalled
|
||||
MOVS r2, #2
|
||||
TST r0, r2
|
||||
BNE send_STALL
|
||||
|
||||
// check if endpoint contains data
|
||||
MOVS r1, #1
|
||||
TST r0, r1 // if equal => Endpoint buffer is free
|
||||
BNE send_NAK
|
||||
|
||||
// here: buffer available and endpoint not stalled, so copy data to buffer...
|
||||
MOV r0, r8
|
||||
MOV r1, r9
|
||||
MOV r2, r10
|
||||
MOV r5, r6 // generate address to EP0buffer data
|
||||
STM r5!, {r0, r1, r2} // copy data to EP0OUT buffer
|
||||
MOV r0, r11 // EP0OUT_LEN is filled with the received bitcount (includes PID & CRC)
|
||||
STRB r0, [r6, #USBEP_SOFS_LEN]
|
||||
|
||||
LDRB r1, [r6, #USBEP_SOFS_STAT]
|
||||
MOVS r0, #1
|
||||
ORRS r1, r1, r0
|
||||
STRB r1, [r6, #USBEP_SOFS_STAT] // set "data available" flag for EP0OUT Buffer
|
||||
B send_ACK
|
||||
|
||||
pid_data_setup: LDR r6, ASM_USB_EP_BUFFERS // copy setup data to buffer
|
||||
MOV r0, r8
|
||||
MOV r1, r9
|
||||
MOV r2, r10
|
||||
MOV r5, r6 // generate address to EP0buffer data
|
||||
ADDS r5, r5, #USBEP_OFS_SETUP
|
||||
STM r5!, {r0, r1, r2} // copy data to SETUP buffer
|
||||
LDRB r1, [r6, #(USBEP_OFS_SETUP + USBEP_SOFS_STAT)]
|
||||
MOVS r0, #1
|
||||
ORRS r1, r1, r0
|
||||
STRB r1, [r6, #(USBEP_OFS_SETUP + USBEP_SOFS_STAT)] // set "data available" flag for SETUP BUFFER
|
||||
|
||||
// SEND ACK... This is the only option. NAK is not allowed in a setup phase
|
||||
B send_ACK
|
||||
|
||||
|
||||
pid_in: MOVS r0, #2
|
||||
STRB r0, [r7] // Flag, that an IN PID was received
|
||||
|
||||
// extract address
|
||||
MOV r0, r8
|
||||
LSRS r1, r0, #16
|
||||
MOVS r2, #0xfe
|
||||
ANDS r1, r1, r2 // Mask out address bits a0-a6. Order: a0 a1 a2 a3 a4 a5 a6 0
|
||||
STRB r1, [r7, #1] // Store address in protocol state
|
||||
|
||||
// check if USB Address is for this device
|
||||
CMP r1, r3
|
||||
BNE jump_exit // This device is not addressed => Don't react on DATA PID
|
||||
|
||||
// extract endpoint number
|
||||
LSRS r1, r0, #9
|
||||
MOVS r2, #0xf0
|
||||
ANDS r1, r1, r2
|
||||
STRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
|
||||
// build pointer to correct endpoint buffer
|
||||
LDR r5, ASM_USB_EP_BUFFERS
|
||||
CMP r1, #0
|
||||
BEQ pid_in_ep0_addressed
|
||||
ADDS r5, r5, #USBEP_OFS_EP1IN
|
||||
B pid_in_ep1_addressed
|
||||
pid_in_ep0_addressed: ADDS r5, r5, #USBEP_OFS_EP0IN
|
||||
pid_in_ep1_addressed:
|
||||
|
||||
// check stall condition
|
||||
LDRB r0, [r5, #USBEP_SOFS_STAT] // Bit0 = 0 = no data available => send NAK, Bit 0 = 1 = data availabe => send data
|
||||
MOVS r2, #2
|
||||
TST r0, r2
|
||||
BNE send_STALL // Check and handle Endpoint STALL condition
|
||||
|
||||
// check if data is available in addressed endpoint
|
||||
MOVS r1, #1
|
||||
TST r0, r1
|
||||
BEQ send_NAK
|
||||
// send Data. Important: First byte contains correct DATA PID (DATA0/DATA1)
|
||||
|
||||
PUSH {r5}
|
||||
LDM r5!, {r0, r1, r2}
|
||||
LDRB r5, [r5, #1] // => USBEP_SOFS_LEN
|
||||
LSLS r5, r5, #3 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
POP {r5}
|
||||
|
||||
LDRB r1, [r5, #USBEP_SOFS_STAT]
|
||||
MOVS r0, #0xfe
|
||||
ANDS r1, r1, r0
|
||||
STRB r1, [r5, #USBEP_SOFS_STAT] // Flag EP0IN as empty
|
||||
B jump_exit
|
||||
|
||||
|
||||
pid_out: MOVS r0, #1
|
||||
STRB r0, [r7] // Flag, that the next data package is for an endpoint
|
||||
MOV r0, r8
|
||||
// extract address
|
||||
LSRS r1, r0, #16
|
||||
MOVS r2, #0xfe
|
||||
ANDS r1, r1, r2 // Mask out address bits a0-a6. Order: a0 a1 a2 a3 a4 a5 a6 0
|
||||
STRB r1, [r7, #1] // Store address in protocol state
|
||||
|
||||
// extract endpoint number
|
||||
LSRS r1, r0, #9
|
||||
MOVS r2, #0xf0
|
||||
ANDS r1, r1, r2
|
||||
STRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
B jump_exit
|
||||
|
||||
|
||||
|
||||
// Status return functions (function => host)
|
||||
send_STALL: MOVS r0, #USB_TOKEN_STALL
|
||||
MOVS r5, #8 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
B jump_exit
|
||||
|
||||
send_NAK: MOVS r0, #USB_TOKEN_NAK
|
||||
MOVS r5, #8 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
B jump_exit
|
||||
|
||||
send_ACK: MOVS r0, #USB_TOKEN_ACK
|
||||
MOVS r5, #8 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
B jump_exit
|
||||
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
|
||||
DATA
|
||||
ALIGNROM 2
|
||||
ASM_USB_PROT_STATE: DC32 USB_PROT_STATE
|
||||
ASM_USB_EP_BUFFERS: DC32 usb_ep_buffers
|
||||
ASM_USB_DEV_ADDRESS: DC32 usb_dev_address
|
||||
LBL_PROT_HANDLED: DC32 protocol_handled
|
||||
|
||||
END
|
||||
#else
|
||||
|
||||
.BALIGN 4
|
||||
ASM_USB_PROT_STATE: .long USB_PROT_STATE
|
||||
ASM_USB_EP_BUFFERS: .long usb_ep_buffers
|
||||
ASM_USB_DEV_ADDRESS: .long usb_dev_address
|
||||
LBL_PROT_HANDLED: .long protocol_handled
|
||||
.END
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "usb_stack.h"
|
||||
#include "usb.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_helperfunctions.h"
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
#include "usb_hid.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Standard Request codes for Control */
|
||||
#define SRQ_GET_STATUS (0x00) /* Standard Request : Get Status */
|
||||
#define SRQ_CLEAR_FEATURE (0x01) /* Standard Request : Clear Feature */
|
||||
#define SRQ_RESERVED1 (0x02) /* Standard Request : Reserved for future use */
|
||||
#define SRQ_SET_FEATURE (0x03) /* Standard Request : Set Feature */
|
||||
#define SRQ_RESERVED2 (0x04) /* Standard Request : Reserved for future use */
|
||||
#define SRQ_SET_ADDRESS (0x05) /* Standard Request : Set Address */
|
||||
#define SRQ_GET_DESCRIPTOR (0x06) /* Standard Request : Get Descriptor */
|
||||
#define SRQ_SET_DESCRIPTOR (0x07) /* Standard Request : Set Descriptor */
|
||||
#define SRQ_GET_CONFIGURATION (0x08) /* Standard Request : Get Configuration */
|
||||
#define SRQ_SET_CONFIGURATION (0x09) /* Standard Request : Set Configuration */
|
||||
#define SRQ_GET_INTERFACE (0x0a) /* Standard Request : Get Interface */
|
||||
#define SRQ_SET_INTERFACE (0x0b) /* Standard Request : Set Interface */
|
||||
#define SRQ_SYNCH_FRAME (0x0c) /* Standard Request : Synch Frame */
|
||||
|
||||
/* Status type codes used in SRQ_GET_STATUS request */
|
||||
#define STATUS_DEVICE (0x80) /* Get Status: Device */
|
||||
#define STATUS_INTERFACE (0x81) /* Get Status: Interface */
|
||||
#define STATUS_ENDPOINT (0x82) /* Get Status: End Point */
|
||||
|
||||
/* Feature type codes used in SRQ_SET_FEATURE request */
|
||||
#define FEATURE_DEVICE (0x00) /* Feature: Device */
|
||||
#define FEATURE_ENDPOINT (0x02) /* Feature: End Point */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t usb_dev_address; /* default address is 0x00 TODO: Reset to zero when a reset condition is present on BUS (SE0 long duration) */
|
||||
static uint8_t usb_dev_configuration;
|
||||
static uint8_t usb_dev_alternatesetting;
|
||||
static uint8_t usb_dev_Rwuen;
|
||||
static uint8_t usb_dev_selfpwr;
|
||||
|
||||
|
||||
|
||||
|
||||
void usbstack_init(void)
|
||||
{
|
||||
usb_dev_address = 0x00;
|
||||
usb_dev_configuration = 0;
|
||||
usb_dev_alternatesetting = 0;
|
||||
usb_dev_Rwuen = 0;
|
||||
usb_dev_selfpwr = 0;
|
||||
}
|
||||
|
||||
|
||||
bool usbstack_got_setup_cmd(const setupData_t *psetupdata)
|
||||
{
|
||||
uint8_t response[8];
|
||||
uint16_t clen;
|
||||
bool handled;
|
||||
|
||||
handled = true;
|
||||
|
||||
switch(psetupdata->bRequest)
|
||||
{
|
||||
case SRQ_SET_ADDRESS: /* This needs to be done within 50ms after receiving the setup packet! */
|
||||
usb_control_acknowledge();
|
||||
while (!usb_ep_in_buf_empty(0)); /* Wait until the complete setup transfer is finished, before setting the usb device address */
|
||||
usb_dev_address = bitreverse(psetupdata->wValue);
|
||||
/* set Address does not have an OUT stage */
|
||||
break;
|
||||
case SRQ_GET_DESCRIPTOR: // *** Get Descriptor
|
||||
switch (psetupdata->wValue >> 8)
|
||||
{
|
||||
case DESCRIPTOR_DEVICE: // Device
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(device_descriptor)) clen = sizeof(device_descriptor);
|
||||
usb_control_dataIn(device_descriptor, clen);
|
||||
break;
|
||||
case DESCRIPTOR_CONFIGURATION: // Configuration setupdat[2] contains configuration number
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(config_0_descriptor))
|
||||
{
|
||||
clen = sizeof(config_0_descriptor);
|
||||
}
|
||||
usb_control_dataIn(config_0_descriptor, clen); /* setupdat[2] specifies configurationnumber, currently fixed to 0 */
|
||||
|
||||
if (clen == 0x09)
|
||||
{
|
||||
volatile int i;
|
||||
i++;
|
||||
}
|
||||
|
||||
break;
|
||||
case DESCRIPTOR_STRING: // String setupdat[2] contains string index
|
||||
switch (psetupdata->wValue & 0xff)
|
||||
{
|
||||
case 0:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(string_0_descriptor)) clen = sizeof(string_0_descriptor);
|
||||
usb_control_dataIn(string_0_descriptor, clen);
|
||||
break;
|
||||
case 1:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(string_1_descriptor)) clen = sizeof(string_1_descriptor);
|
||||
usb_control_dataIn(string_1_descriptor, clen);
|
||||
break;
|
||||
case 2:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(string_2_descriptor)) clen = sizeof(string_2_descriptor);
|
||||
usb_control_dataIn(string_2_descriptor, clen);
|
||||
break;
|
||||
default:
|
||||
usb_control_dataIn(response, 0);
|
||||
break;
|
||||
/* INFO: more/less string descriptors can be used. String descriptors are not mandatory! */
|
||||
}
|
||||
break;
|
||||
#ifdef USB_ENABLE_HID
|
||||
case DESCRIPTOR_REPORT:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(hid_report_descriptor)) clen = sizeof(hid_report_descriptor);
|
||||
usb_control_dataIn(hid_report_descriptor, clen);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
handled = false;
|
||||
}
|
||||
break;
|
||||
case SRQ_GET_INTERFACE:
|
||||
response[0] = usb_dev_alternatesetting;
|
||||
usb_control_dataIn(response, 1);
|
||||
break;
|
||||
case SRQ_SET_INTERFACE:
|
||||
usb_dev_alternatesetting = psetupdata->wValue;
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
case SRQ_SET_CONFIGURATION:
|
||||
usb_dev_configuration = psetupdata->wValue;
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
case SRQ_GET_CONFIGURATION:
|
||||
response[0] = usb_dev_configuration;
|
||||
usb_control_dataIn(response, 1);
|
||||
break;
|
||||
case SRQ_GET_STATUS:
|
||||
switch(psetupdata->bmRequestType)
|
||||
{
|
||||
case STATUS_DEVICE:
|
||||
response[0] = (usb_dev_Rwuen << 1) | usb_dev_selfpwr;
|
||||
response[1] = 0;
|
||||
usb_control_dataIn(response, 2);
|
||||
break;
|
||||
case STATUS_INTERFACE:
|
||||
response[0] = 0;
|
||||
response[1] = 0;
|
||||
usb_control_dataIn(response, 2);
|
||||
break;
|
||||
case STATUS_ENDPOINT:
|
||||
response[0] = 0; /* TODO: return if endpoint is stalled */
|
||||
response[1] = 0;
|
||||
usb_control_dataIn(response, 2);
|
||||
break;
|
||||
default:
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
handled = false;
|
||||
}
|
||||
break;
|
||||
case SRQ_CLEAR_FEATURE:
|
||||
switch(psetupdata->bmRequestType)
|
||||
{
|
||||
case FEATURE_DEVICE:
|
||||
if(psetupdata->wValue == 1)
|
||||
usb_dev_Rwuen = 0; /* Disable Remote Wakeup */
|
||||
else
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
case FEATURE_ENDPOINT:
|
||||
if ( (psetupdata->wValue & 0x0f) == 0 )
|
||||
{
|
||||
usb_ep_unstall(USB_EP0OUT);
|
||||
usb_ep_unstall(USB_EP0IN);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_ep_unstall(USB_EP1OUT);
|
||||
usb_ep_unstall(USB_EP1IN);
|
||||
}
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SRQ_SET_FEATURE:
|
||||
switch(psetupdata->bmRequestType)
|
||||
{
|
||||
case FEATURE_DEVICE:
|
||||
if (psetupdata->wValue == 1)
|
||||
usb_dev_Rwuen = 1; /* enable remote wakeup */
|
||||
else
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
break;
|
||||
case FEATURE_ENDPOINT:
|
||||
if ( (psetupdata->wValue & 0x0f) == 0 )
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_ep_stall(USB_EP1OUT);
|
||||
usb_ep_stall(USB_EP1IN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
handled = false;
|
||||
}
|
||||
|
||||
|
||||
return handled;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_STACK_H__
|
||||
#define __USB_STACK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
/* These defines can be used to mask out the bmRequestType bits */
|
||||
#define USB_SETUP_BM_DIRECTION (0x80)
|
||||
#define USB_SETUP_BM_TYPE (0x60)
|
||||
#define USB_SETUP_BM_RECIPIENT (0x1f)
|
||||
|
||||
#define USB_SETUP_DIR_DEV_TO_HOST (0x80)
|
||||
|
||||
#define USB_SETUP_TYPE_STANDARD (0 << 5)
|
||||
#define USB_SETUP_TYPE_CLASS (1 << 5)
|
||||
#define USB_SETUP_TYPE_VENDOR (2 << 5)
|
||||
|
||||
#define USB_SETUP_DEVICE (0x00)
|
||||
#define USB_SETUP_INTERFACE (0x01)
|
||||
#define USB_SETUP_ENDPOINT (0x02)
|
||||
#define USB_SETUP_OTHER (0x03)
|
||||
|
||||
void usbstack_init(void);
|
||||
|
||||
|
||||
/* call this function when setup data was received
|
||||
TODO: allow user to call this also, when no setup data was received.
|
||||
I think the best way is to let the user only call functions from this file and not from usb.h */
|
||||
bool usbstack_got_setup_cmd(const setupData_t *psetupdata);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file pmc.c
|
||||
* @brief 电源管理模块(PMC)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
*****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "pmc.h"
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PMC模块初始化函数
|
||||
*
|
||||
* @param[in] pPMC_Config PMC 配置结构体.
|
||||
* @param[in] pPMC PMC
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PMC_Init(PMC_Type *pPMC, PMC_ConfigType *pPMC_Config)
|
||||
{
|
||||
pPMC->SPMSC1 = pPMC_Config->sCtrlstatus.byte;
|
||||
pPMC->SPMSC2 = pPMC_Config->sDetectVoltSelect.byte;
|
||||
if(pPMC_Config->sCtrlstatus.bits.bLvwIrqEn)
|
||||
NVIC_EnableIRQ(LVD_LVW_IRQn);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位PMC模块.
|
||||
*
|
||||
* @param[in] pPMC PMC
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PMC_DeInit(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 = 0x1C;
|
||||
pPMC->SPMSC2 = 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief MCU工作模式选择函数
|
||||
*
|
||||
* @param[in] u8PmcMode 选择MCU工作模式.
|
||||
* @param[in] pPMC PMC
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PMC_SetMode(PMC_Type *pPMC,uint8_t u8PmcMode)
|
||||
{
|
||||
switch(u8PmcMode & 0x3)
|
||||
{
|
||||
case PmcModeRun:
|
||||
break;
|
||||
case PmcModeWait: //等待模式
|
||||
wait();
|
||||
break;
|
||||
case PmcModeStop4:
|
||||
/* 停止模式下,使能低压检测*/
|
||||
pPMC->SPMSC1 |= (PMC_SPMSC1_LVDE_MASK | PMC_SPMSC1_LVDSE_MASK);
|
||||
stop();
|
||||
break;
|
||||
case PmcModeStop3:
|
||||
/* 在停止模式下,禁用低压检测*/
|
||||
pPMC->SPMSC1 &= ~(PMC_SPMSC1_LVDE_MASK | PMC_SPMSC1_LVDRE_MASK | PMC_SPMSC1_LVDSE_MASK);
|
||||
stop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief PMC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef PMC_H_
|
||||
#define PMC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* PCM系统(MCU工作模式)模式定义
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define PmcModeRun 0 /*!< 运行模式 */
|
||||
#define PmcModeWait 1 /*!< 等到模式 */
|
||||
#define PmcModeStop4 2 /*!< 停止模式4 */
|
||||
#define PmcModeStop3 3 /*!< 停止模式3 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 低压检测和低压报警电压定义
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define PmcLVDTrip_Low 0 /*!< LVD 低电平调变点 */
|
||||
#define PmcLVDTrip_High 1 /*!< LVD 高电平调变点 */
|
||||
|
||||
#define PmcLVWTrip_Low 0 /*!< LVW 低电平跳变点 */
|
||||
#define PmcLVWTrip_Mid1 1 /*!< LVW 中间电平1跳变点 */
|
||||
#define PmcLVWTrip_Mid2 2 /*!< LVW 中间电平2跳变点*/
|
||||
#define PmcLVWTrip_High 3 /*!< LVW 高电平跳变点*/
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 控制结构体
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief PMC控制结构体类型
|
||||
*
|
||||
*/
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!< 联合体的类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bBandgapEn :1; /*!< 使能带隙缓冲区 */
|
||||
uint8_t bBandgapDrv :1; /*!< 选择带隙驱动*/
|
||||
uint8_t bLvdEn :1; /*!< 使能低压检测*/
|
||||
uint8_t bLvdStopEn :1; /*!< 低压检测在停止模式下使能*/
|
||||
uint8_t bLvdRstEn :1; /*!< 使能低压检测复位 */
|
||||
uint8_t bLvwIrqEn :1; /*!< 使能低压报警中断 */
|
||||
uint8_t bLvwAck :1; /*!< 低压报警应答 */
|
||||
uint8_t bLvwFlag :1; /*!< 低压报警标志 */
|
||||
}bits; /*!< 联合体类型-位 */
|
||||
}PMC_Ctrl1Type, *PMC_Ctrl1Ptr; /*!< PMC 控制寄存器1结构体 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 控制-- 低压选择.
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief PMC 控制-- 电压类型选择.
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!< 联合体类型-字节 */
|
||||
struct
|
||||
{
|
||||
uint8_t :4; /*!< none */
|
||||
uint8_t bLVWV :2; /*!< 低压报警电压选择 */
|
||||
uint8_t bLVDV :1; /*!< 低压复位电压选择 */
|
||||
uint8_t :1; /*!< none */
|
||||
}bits; /*!< 结构体类型——位 */
|
||||
}PMC_Ctrl2Type, *PMC_Ctrl2Ptr; /*!< PMC 控制寄存器2结构体*/
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 配置结构体
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PMC_Ctrl1Type sCtrlstatus; /*!< PMC 控制和状态 */
|
||||
PMC_Ctrl2Type sDetectVoltSelect; /*!< 低压报警电压和低压复位电压选择*/
|
||||
}PMC_ConfigType, *PMC_ConfigPtr; /*!< PMC 配置结构体 */
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下使能低压检测.
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVDInStopMode.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVDInStopMode(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVDSE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下禁用低压检测
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_EnableLVDInStopMode.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVDInStopMode(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVDSE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能低压检测复位 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVDRst.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVDRst(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVDRE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用低压检测复位 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_EnableLVDRst.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVDRst(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVDRE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能低压检测, 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVD.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVD(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVDE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用低压检测, 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_EnableLVD.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVD(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVDE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置低压检测跳变点,
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
* @param[in] Trippoint 电压检测跳变点选择,1-高电平跳变 0-低电平跳变
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_SetLVWTripVolt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_SetLVDTripVolt(PMC_Type *pPMC, uint8_t Trippoint)
|
||||
{
|
||||
if(Trippoint)
|
||||
pPMC->SPMSC2 |= PMC_SPMSC2_LVDV_MASK;
|
||||
else
|
||||
pPMC->SPMSC2 &= ~PMC_SPMSC2_LVDV_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择电压报警跳变点电压
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
* @param[in] Trippoint 低压报警跳变点电压 0 低电平跳变 1 中间电平1跳变
|
||||
* 2 中间电平2跳变 3 高电平跳变
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_SetLVDTripVolt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_SetLVWTripVolt(PMC_Type *pPMC, uint8_t Trippoint)
|
||||
{
|
||||
pPMC->SPMSC2 &= ~PMC_SPMSC2_LVWV_MASK;
|
||||
pPMC->SPMSC2 |= PMC_SPMSC2_LVWV(Trippoint);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能低压报警中断
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVWInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVWInterrupt(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVWIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用低压报警中断
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see PMC_EnableLVWInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVWInterrupt(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVWIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取低压报警标志位.
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return 低压报警标志位值
|
||||
*
|
||||
* @see PMC_ClrLVWFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t PMC_GetLVWFlag(PMC_Type *pPMC)
|
||||
{
|
||||
return (pPMC->SPMSC1 & PMC_SPMSC1_LVWF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除低压报警标志位
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_GetLVWFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_ClrLVWFlag(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVWACK_MASK;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
void PMC_Init(PMC_Type *pPMC, PMC_ConfigType *pPMC_Config);
|
||||
void PMC_DeInit(PMC_Type *pPMC);
|
||||
void PMC_SetMode(PMC_Type *pPMC,uint8_t u8PmcMode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,169 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file acmp.c
|
||||
* @brief 模拟比较器(ACMP)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "acmp.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放ACMP回调函数接口
|
||||
****************************************************************************/
|
||||
ACMP_CallbackPtr ACMP_Callback[2] = {(ACMP_CallbackPtr)NULL};
|
||||
|
||||
/**************************************************************************/
|
||||
void ACMP0_Isr(void);
|
||||
void ACMP1_Isr(void);
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化ACMP模块
|
||||
*
|
||||
* @param pACMPx 指向ACMP寄存器基址
|
||||
* @param pConfig 控制参数
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DeInit.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_Init(ACMP_Type *pACMPx, ACMP_ConfigType *pConfig)
|
||||
{
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
/* 使能ACMP模块的总线时钟 */
|
||||
SIM->SCGC |= SIM_SCGC_ACMP0_MASK;
|
||||
|
||||
/* 使能ACMP中断 */
|
||||
if(pConfig->sCtrlStatus.bits.bIntEn)
|
||||
NVIC_EnableIRQ(ACMP0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ACMP1_MASK;
|
||||
if(pConfig->sCtrlStatus.bits.bIntEn)
|
||||
NVIC_EnableIRQ(ACMP1_IRQn);
|
||||
}
|
||||
/*选择ACMP正输入和负输入,正输入和负输入引脚不同*/
|
||||
pACMPx->C0 = pConfig->sPinSelect.byte;
|
||||
ACMP_ConfigDAC(pACMPx, &pConfig->sDacSet );
|
||||
//pACMPx->C1 = pConfig->sDacSet.byte;
|
||||
pACMPx->C2 = pConfig->sPinEnable.byte;
|
||||
pACMPx->CS = pConfig->sCtrlStatus.byte;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置ACMP控制寄存器1.
|
||||
*
|
||||
* @param pACMPx 指向ACMP模块寄存器基地址
|
||||
* @param pDACConfig 指向 ACMP DAC 控制结构体.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_ConfigDAC(ACMP_Type *pACMPx, ACMP_DACType *pDACConfig)
|
||||
{
|
||||
pACMPx->C1 = pDACConfig->byte;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位ACMP模块.
|
||||
*
|
||||
* @param pACMPx 指向ACMP模块寄存器基地址
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_Init.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_DeInit(ACMP_Type *pACMPx)
|
||||
{
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
if(pACMPx->CS & ACMP_CS_ACIE_MASK)
|
||||
NVIC_DisableIRQ(ACMP0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pACMPx->CS & ACMP_CS_ACIE_MASK)
|
||||
NVIC_DisableIRQ(ACMP1_IRQn);
|
||||
}
|
||||
|
||||
pACMPx->CS = 0;
|
||||
pACMPx->C0 = 0;
|
||||
pACMPx->C1 = 0;
|
||||
pACMPx->C2 = 0;
|
||||
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ACMP0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ACMP1_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ACMP回调函数,通过中断服务函数调用回调函数.
|
||||
*
|
||||
* @param pACMPx 指向ACMP模块寄存器基地址.
|
||||
* @param pfnCallback 回调函数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_SetCallback(ACMP_Type *pACMPx, ACMP_CallbackPtr pfnCallback)
|
||||
{
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
ACMP_Callback[0] = pfnCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
ACMP_Callback[1] = pfnCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP0 中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP0_Isr(void)
|
||||
{
|
||||
if(ACMP_Callback[0])
|
||||
{
|
||||
ACMP_Callback[0](); /*调用回调函数*/
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP1 中断服务函数
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP1_Isr(void)
|
||||
{
|
||||
if(ACMP_Callback[1])
|
||||
{
|
||||
ACMP_Callback[1](); /* 调用回调函数*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,455 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ACMP 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _MY_ACMP_H_
|
||||
#define _MY_ACMP_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/* 选择DAC基准 */
|
||||
enum
|
||||
{
|
||||
DAC_REF_BANDGAP = 0,
|
||||
DAC_REF_VDDA
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* ACMP 模块数定义
|
||||
******************************************************************************/
|
||||
#define MAX_ACMP_NO 2
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 定义ACMP 正输入和负输入引脚
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_INPUT_P_EXT0 (0<<4) /*!< ACMP正输入选择外部基准0 */
|
||||
#define ACMP_INPUT_P_EXT1 (1<<4) /*!< ACMP正输入选择外部基准1 */
|
||||
#define ACMP_INPUT_P_EXT2 (2<<4) /*!< ACMP正输入选择外部基准2 */
|
||||
#define ACMP_INPUT_P_DAC (3<<4) /*!< ACMP正输入选择DAC输出 */
|
||||
#define ACMP_INPUT_N_EXT0 0 /*!< ACMP负输入选择外部基准0 */
|
||||
#define ACMP_INPUT_N_EXT1 1 /*!< ACMP负输入选择外部基准1 */
|
||||
#define ACMP_INPUT_N_EXT2 2 /*!< ACMP负输入选择外部基准2 */
|
||||
#define ACMP_INPUT_N_DAC 3 /*!< ACMP负输入选择DAC输出 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ACMP中断触发器的触发模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_SENSITIVITYMODE_FALLING 0 /*!< ACMP中断在输出下降沿发生 */
|
||||
#define ACMP_SENSITIVITYMODE_RISING 1 /*!< ACMP中断在输出上升沿发生 */
|
||||
#define ACMP_SENSITIVITYMODE_ANY 3 /*!< ACMP中断在输出上升沿或下降沿触发 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ACMP 迟滞
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_HYST_20MV (0<<6) /*!< 20mv */
|
||||
#define ACMP_HYST_30MV (1<<6) /*!< 30mv */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义内部DAC参考基准
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_DAC_REFERENCE_BANDGAP (0<<6) /*!< 选择带隙为基准 */
|
||||
#define ACMP_DAC_REFERENCE_VDDA (1<<6) /*!< 选择VDDA为基准 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP回调函数声明
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*ACMP_CallbackPtr)(void);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 控制和状态字寄存器结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bMod : 2; /*!< 中断触发模式 */
|
||||
uint8_t bOutEn : 1; /*!< ACMP输出置于外部引脚 */
|
||||
uint8_t bOutState : 1; /*!< 模拟比较强输出的当前值 */
|
||||
uint8_t bIntEn : 1; /*!< 使能ACMP中断 */
|
||||
uint8_t bIntFlag : 1; /*!< ACMP 中断标志位 */
|
||||
uint8_t bHyst : 1; /*!< 选择ACMP迟滞 */
|
||||
uint8_t bEn : 1; /*!< 使能ACMP模块 */
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_CtrlStatusType, *ACMP_CtrlStatusPtr; /*!< ACMP 控制和状态寄存器结构*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 外部输入引脚控制结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bNegPin : 2; /*!< 负输入选择*/
|
||||
uint8_t : 2;
|
||||
uint8_t bPosPin : 2; /*!< 正输入选择 */
|
||||
uint8_t : 2;
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_PinSelType, *ACMP_PinSelPtr; /*!< ACMP 输入选择结构体 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 内部DAC控制结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bVal : 6; /*!< DAC输出电平选择*/
|
||||
uint8_t bRef : 1; /*!< DAC基准选择 */
|
||||
uint8_t bEn : 1; /*!< DAC使能 */
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_DACType, *ACMP_DACPtr; /*!< ACMP DAC 控制结构体 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 外部输入引脚使能控制结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bEn : 3; /*!< ACMP 外部输入引脚使能 */
|
||||
uint8_t bRsvd : 5;
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_PinEnType, *ACMP_PinEnPtr; /*!< ACMP 引脚使能结构体 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 模块配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
ACMP_CtrlStatusType sCtrlStatus; /*!< ACMP 控制和状体 */
|
||||
ACMP_PinSelType sPinSelect; /*!< ACMP 输入选择 */
|
||||
ACMP_DACType sDacSet; /*!< ACMP 内部DAC控制 */
|
||||
ACMP_PinEnType sPinEnable; /*!< ACMP 外部输入引脚使能控制 */
|
||||
}ACMP_ConfigType, *ACMP_ConfigPtr;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP模块
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_Disable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_Enable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS |= ACMP_CS_ACE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP模块
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_Enable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_Disable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ACMP中断触发器的触发模式.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
* @param[in] u8EdgeSelect 上升沿或下降沿选择, 0~3.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_SelectIntMode(ACMP_Type *pACMPx, uint8_t u8EdgeSelect)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACMOD_MASK;
|
||||
pACMPx->CS |= ACMP_CS_ACMOD(u8EdgeSelect & 0x3);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP输出置于外部引脚上
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DisablePinOut.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_EnablePinOut(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS |= ACMP_CS_ACOPE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP输出置于外部引脚上
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_EnablePinOut.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DisablePinOut(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACOPE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ACMP迟滞
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8HystSelect 2mv or 30mv.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_SelectHyst(ACMP_Type *pACMPx, uint8_t u8HystSelect)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_HYST_MASK;
|
||||
pACMPx->CS |= u8HystSelect;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP模块中断
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see ACMP_DisableInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_EnableInterrupt(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS |= ACMP_CS_ACIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP模块中断
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_EnableInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DisableInterrupt(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取中断标志位
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_ClrFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ACMP_GetFlag(ACMP_Type *pACMPx)
|
||||
{
|
||||
return (pACMPx->CS & ACMP_CS_ACF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除中断标志位
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_GetFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_ClrFlag(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACF_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP正输入选择
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
* @param[in] u8PosPinSel 正输入选择, 外部基准0~2 或DAC输出.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_NegativeInputSelect.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_PositiveInputSelect(ACMP_Type *pACMPx, uint8_t u8PosPinSel)
|
||||
{
|
||||
pACMPx->C0 &= ~ACMP_C0_ACPSEL_MASK;
|
||||
pACMPx->C0 |= u8PosPinSel;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP负输入选择.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
* @param[in] u8NegPinSel 负输入选择, 外部基准0~2 或DAC输出.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_PositiveInputSelect.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_NegativeInputSelect(ACMP_Type *pACMPx, uint8_t u8NegPinSel)
|
||||
{
|
||||
pACMPx->C0 &= ~ACMP_C0_ACNSEL_MASK;
|
||||
pACMPx->C0 |= u8NegPinSel;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能内部DAC
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DacDisable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacEnable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->C1 |= ACMP_C1_DACEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用内部DAC
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DacEnable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacDisable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->C1 &= ~ACMP_C1_DACEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief DAC基准选择
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8RefSelect DAC参考选择: 带隙 or VDDA.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacReferenceSelect(ACMP_Type *pACMPx, uint8_t u8RefSelect)
|
||||
{
|
||||
pACMPx->C1 &= ~ACMP_C1_DACREF_MASK;
|
||||
pACMPx->C1 |= u8RefSelect;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief DAC输出电平选择
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8DacValue DAC输出选择, Voutput= (Vin/64)x(DACVAL[5:0]+1).
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacOutputSet(ACMP_Type *pACMPx, uint8_t u8DacValue)
|
||||
{
|
||||
ASSERT(!(u8DacValue & (~ACMP_C1_DACVAL_MASK)));
|
||||
pACMPx->C1 &= ~ACMP_C1_DACVAL_MASK;
|
||||
pACMPx->C1 |= ACMP_C1_DACVAL(u8DacValue);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP外部输入引脚.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8InputPin ACMP 外部输入引脚, 0~2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_InputPinEnable(ACMP_Type *pACMPx, uint8_t u8InputPin)
|
||||
{
|
||||
ASSERT(!(u8InputPin & (~ACMP_C2_ACIPE_MASK)));
|
||||
pACMPx->C2 |= ACMP_C2_ACIPE(u8InputPin);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP外部输入引脚.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8InputPin ACMP 外部输入引脚, 0~2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_InputPinDisable(ACMP_Type *pACMPx, uint8_t u8InputPin)
|
||||
{
|
||||
ASSERT(!(u8InputPin & (~ACMP_C2_ACIPE_MASK)));
|
||||
pACMPx->C2 &= ~ACMP_C2_ACIPE(u8InputPin);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void ACMP_Init(ACMP_Type *pACMPx, ACMP_ConfigType *pConfig);
|
||||
void ACMP_DeInit(ACMP_Type *pACMPx);
|
||||
void ACMP_ConfigDAC(ACMP_Type *pACMPx, ACMP_DACType *pDACConfig);
|
||||
void ACMP_SetCallback(ACMP_Type *pACMPx, ACMP_CallbackPtr pfnCallback);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,256 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file adc.c
|
||||
* @brief 数模转换模块(ADC)库函数��
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "adc.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放ACMP回调函数接口
|
||||
****************************************************************************/
|
||||
ADC_CallbackType ADC_Callback[1] = {NULL};
|
||||
|
||||
/*****************************************************************************//**
|
||||
*
|
||||
* @brief 初始化ADC模块.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块类型.
|
||||
* @param[in] pADC_Config 指向ADC模块配置结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_Init(ADC_Type *pADC, ADC_ConfigTypePtr pADC_Config)
|
||||
{
|
||||
if( pADC == ADC)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ADC_MASK;
|
||||
}
|
||||
/* 选择ADC模块时钟源 */
|
||||
ADC_SelectClock(pADC,pADC_Config->u8ClockSource);
|
||||
/* 设定时钟分频 */
|
||||
ADC_SelectClockDivide(pADC,pADC_Config->u8ClockDiv);
|
||||
/* 设置ADC转换模式 */
|
||||
ADC_SetMode(pADC,pADC_Config->u8Mode);
|
||||
/* 设置FIFO深度 */
|
||||
ADC_SetFifoLevel(pADC,pADC_Config->u8FiFoLevel);
|
||||
/* ADC输入引脚控制 */
|
||||
pADC->APCTL1 = pADC_Config->u16PinControl;
|
||||
if( pADC_Config->sSetting.bCompareEn )
|
||||
{
|
||||
ADC_CompareEnable(pADC); //使能ADC比较功能
|
||||
}
|
||||
if( pADC_Config->sSetting.bCompareGreaterEn )
|
||||
{
|
||||
ADC_CompareGreaterFunction(pADC); //输入大于或等于比较电平时比较触发
|
||||
}
|
||||
if( pADC_Config->sSetting.bContinuousEn )
|
||||
{
|
||||
ADC_ContinuousConversion(pADC); // 使能ADC连续转换.
|
||||
}
|
||||
if( pADC_Config->sSetting.bCompareAndEn )
|
||||
{
|
||||
ADC_CompareFifoAnd(pADC); //对所有比较触发做与运算
|
||||
}
|
||||
if( pADC_Config->sSetting.bFiFoScanModeEn )
|
||||
{
|
||||
ADC_FifoScanModeEnable(pADC); //使能FIFO扫描模式
|
||||
}
|
||||
if( pADC_Config->sSetting.bHardwareTriggerEn )
|
||||
{
|
||||
ADC_SetHardwareTrigger(pADC); // 设置ADC硬件触发.
|
||||
}
|
||||
if( pADC_Config->sSetting.bIntEn ) //使能中断
|
||||
{
|
||||
ADC_IntEnable(pADC);
|
||||
NVIC_EnableIRQ( ADC0_IRQn );
|
||||
}
|
||||
if( pADC_Config->sSetting.bLongSampleEn )
|
||||
{
|
||||
ADC_SetLongSample(pADC); // 设置ADC长采样.
|
||||
}
|
||||
if( pADC_Config->sSetting.bLowPowerEn )
|
||||
{
|
||||
ADC_SetLowPower(pADC); // 设置ADC为低功耗模式
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC模块
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块类型
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_DeInit( ADC_Type *pADC )
|
||||
{
|
||||
ADC_SetChannel(pADC,ADC_CHANNEL_DISABLE);
|
||||
SIM->SCGC &= ~SIM_SCGC_ADC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 开始转换和读取转换结果
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Channel ADC转换通道
|
||||
*
|
||||
* @return ADC 转换结果.
|
||||
*
|
||||
*****************************************************************************/
|
||||
unsigned int ADC_PollRead( ADC_Type *pADC, uint8_t u8Channel )
|
||||
{
|
||||
ADC_SetChannel(pADC,u8Channel);
|
||||
while( !ADC_IsCOCOFlag(pADC) )
|
||||
{
|
||||
;
|
||||
}
|
||||
return ADC_ReadResultReg(pADC);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 注册 ADC 回调函数,通过中断服务函数调用
|
||||
*
|
||||
* @param[in] pADC_CallBack 指向ADC回调函数地址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetCallBack(ADC_CallbackType pADC_CallBack)
|
||||
{
|
||||
ADC_Callback[0] = pADC_CallBack;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ADC输入通道.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u8Channel ADC转换通道
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetChannel( ADC_Type *pADC, uint8_t u8Channel )
|
||||
{
|
||||
uint32_t u32temp;
|
||||
u32temp = pADC->SC1;
|
||||
u32temp &= ~ADC_SC1_ADCH_MASK;
|
||||
pADC->SC1 = u32temp|ADC_SC1_ADCH(u8Channel);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ADC基准电压.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Vref 选择ADC基准电压.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_VrefSelect( ADC_Type *pADC, uint8_t u8Vref )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC2;
|
||||
u32Temp &= ~ADC_SC2_REFSEL_MASK;
|
||||
pADC->SC2 = u32Temp|ADC_SC2_REFSEL(u8Vref);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC时钟源分频
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u8Div 选择分频系数.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SelectClockDivide( ADC_Type *pADC, uint8_t u8Div )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC3;
|
||||
u32Temp &= ~ADC_SC3_ADIV_MASK;
|
||||
pADC->SC3 = u32Temp|ADC_SC3_ADIV(u8Div);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC转换模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Mode 选择ADC转换参数.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetMode( ADC_Type *pADC, uint8_t u8Mode )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC3;
|
||||
u32Temp &= ~ADC_SC3_MODE_MASK;
|
||||
pADC->SC3 = u32Temp|ADC_SC3_MODE(u8Mode);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC输入时钟.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Clock 选择输入时钟源.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SelectClock( ADC_Type *pADC, uint8_t u8Clock )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC3;
|
||||
u32Temp &= ~ADC_SC3_ADICLK_MASK;
|
||||
pADC->SC3 = u32Temp|ADC_SC3_ADICLK(u8Clock);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置FIFO深度
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u8FifoLevel 选择FIFO深度.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetFifoLevel( ADC_Type *pADC, uint8_t u8FifoLevel )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC4;
|
||||
u32Temp &= ~ADC_SC4_AFDEP_MASK;
|
||||
pADC->SC4 = u32Temp|ADC_SC4_AFDEP(u8FifoLevel);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ADC 中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_Isr(void)
|
||||
{
|
||||
if( ADC_Callback[0] )
|
||||
{
|
||||
ADC_Callback[0]();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,655 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ADC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef ADC_H_
|
||||
#define ADC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义ADC参考电压
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_VREF_VREFH 0x00 /*!< ADC 参考电压 VREFH*/
|
||||
#define ADC_VREF_VDDA 0x01 /*!< ADC 参考电压 VDDA*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC时钟源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK 0x00 /*!< ADC时钟源选择总线时钟*/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK_DIVIDE_2 0x01 /*!< ADC时钟源选择总线时钟2分频*/
|
||||
#define CLOCK_SOURCE_ALTCLK 0x02 /*!< ADC时钟源选择备用时钟*/
|
||||
#define CLOCK_SOURCE_ADACK 0x03 /*!< ADC时钟源选择异步时钟*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC源分频系数
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_ADIV_DIVIDE_1 0x00 /*!< ADC时钟源分频系数为1*/
|
||||
#define ADC_ADIV_DIVIDE_2 0x01 /*!< ADC时钟源分频系数为2*/
|
||||
#define ADC_ADIV_DIVIDE_4 0x02 /*!< ADC时钟源分频系数为4*/
|
||||
#define ADC_ADIV_DIVIDE_8 0x03 /*!< ADC时钟源分频系数为8*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_MODE_8BIT 0x00 /*!< 8位转换*/
|
||||
#define ADC_MODE_10BIT 0x01 /*!< 10位转换*/
|
||||
#define ADC_MODE_12BIT 0x02 /*!< 12位转换*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 定义ADC输入通道
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_CHANNEL_AD0 0x0 /*!< ADC输入通道0*/
|
||||
#define ADC_CHANNEL_AD1 0x1 /*!< ADC输入通道1*/
|
||||
#define ADC_CHANNEL_AD2 0x2 /*!< ADC输入通道2*/
|
||||
#define ADC_CHANNEL_AD3 0x3 /*!< ADC输入通道3*/
|
||||
#define ADC_CHANNEL_AD4 0x4 /*!< ADC输入通道4*/
|
||||
#define ADC_CHANNEL_AD5 0x5 /*!< ADC输入通道5*/
|
||||
#define ADC_CHANNEL_AD6 0x6 /*!< ADC输入通道6*/
|
||||
#define ADC_CHANNEL_AD7 0x7 /*!< ADC输入通道7*/
|
||||
#define ADC_CHANNEL_AD8 0x8 /*!< ADC输入通道8*/
|
||||
#define ADC_CHANNEL_AD9 0x9 /*!< ADC输入通道9*/
|
||||
#define ADC_CHANNEL_AD10 0xa /*!< ADC输入通道10*/
|
||||
#define ADC_CHANNEL_AD11 0xb /*!< ADC输入通道11*/
|
||||
#define ADC_CHANNEL_AD12 0xc /*!< ADC输入通道12*/
|
||||
#define ADC_CHANNEL_AD13 0xd /*!< ADC输入通道13*/
|
||||
#define ADC_CHANNEL_AD14 0xe /*!< ADC输入通道14*/
|
||||
#define ADC_CHANNEL_AD15 0xf /*!< ADC输入通道15*/
|
||||
#define ADC_CHANNEL_AD18_VSS 0x12 /*!< ADC输入通道 VSS */
|
||||
#define ADC_CHANNEL_AD22_TEMPSENSOR 0x16 /*!< ADC输入通道温度传感器 */ //Modify
|
||||
#define ADC_CHANNEL_AD23_BANDGAP 0x17 /*!< ADC输入通道带隙 */
|
||||
#define ADC_CHANNEL_AD29_VREFH 0x1D /*!< ADC输入通道 Vrefh */
|
||||
#define ADC_CHANNEL_AD30_VREFL 0x1E /*!< ADC输入通道 Vrefl */
|
||||
#define ADC_CHANNEL_DISABLE 0x1F /*!< ADC输入通道禁用 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义 ADC FIFO 深度
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_FIFO_DISABLE 0 /*!< FIFO禁用*/
|
||||
#define ADC_FIFO_LEVEL2 1 /*!< 2级FIFO */
|
||||
#define ADC_FIFO_LEVEL3 2 /*!< 3级FIFO */
|
||||
#define ADC_FIFO_LEVEL4 3 /*!< 4级FIFO */
|
||||
#define ADC_FIFO_LEVEL5 4 /*!< 5级FIFO */
|
||||
#define ADC_FIFO_LEVEL6 5 /*!< 6级FIFO */
|
||||
#define ADC_FIFO_LEVEL7 6 /*!< 7级FIFO */
|
||||
#define ADC_FIFO_LEVEL8 7 /*!< 8级FIFO */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换触发源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_HARDWARE_TRIGGER 0x01 /*!< 硬件触发 */
|
||||
#define ADC_SOFTWARE_TRIGGER 0x00 /*!< 软件触发 */
|
||||
#define ADC_TRIGGER_RTC 0x00 /*!< 选择RTC溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_PIT 0x01 /*!< 选择PIT0溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_ETM2INIT 0x10 /*!< 选择ETM2初始化化作为硬件触发源 */
|
||||
#define ADC_TRIGGER_ETM2MATCH 0x11 /*!< 选择ETM2匹配作为硬件触发源 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC比较触发模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_COMPARE_LESS 0x00 /*!< 输入小于比较电平时比较触发*/
|
||||
#define ADC_COMPARE_GREATER 0x01 /*!< 输入大于比价电平时比较触发*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC回调函数声明
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*ADC_CallbackType)(void); /*!< ADC回调函数 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC结构体变量
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bIntEn :1; /*!< 1: 中断使能, 0: 禁用中断 */
|
||||
uint16_t bContinuousEn :1; /*!< 1: 使能连续转换模式, 0: 禁用连续转换模式 */
|
||||
uint16_t bHardwareTriggerEn :1; /*!< 1: 硬件触发, 0: 软件触发 */
|
||||
uint16_t bCompareEn :1; /*!< 1: 使能比较模式, 0: 禁用比较模式 */
|
||||
uint16_t bCompareGreaterEn :1; /*!< 1: 输入大于或等于比较电平时比较触发, 0: 输入小于比较电平时比较触发 */
|
||||
uint16_t bLowPowerEn :1; /*!< 1: 低功耗模式, 0: 高速模式 */
|
||||
uint16_t bLongSampleEn :1; /*!< 1: 长采样模式, 0: 短采样模式 */
|
||||
uint16_t bFiFoScanModeEn :1; /*!< 1: 使能FIFO扫描模式, 0: 禁用FIFO扫描模式 */
|
||||
uint16_t bCompareAndEn :1; /*!< 1: 对所有比较触发做与运算, 0: 对所有比较触发做或运算*/
|
||||
#ifdef CPU_NV32
|
||||
uint16_t bReverse :7;
|
||||
#else
|
||||
uint16_t bHTRGMEn :1; /*!< one hardware trigger pulse trigger multiple conversions in fifo mode */
|
||||
uint16_t bHTRGMASKEn :1; /*!< Hardware trigger mask enable. */
|
||||
uint16_t bHTRGMASKSEL :1; /*!< This field selects hardware trigger mask mode. */
|
||||
uint16_t Reserve :4;
|
||||
#endif
|
||||
} ADC_SettingType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
ADC_SettingType sSetting; /*!< ADC配置结构体*/
|
||||
uint16_t u16PinControl; /*!< 引脚控制 */
|
||||
uint8_t u8ClockSource; /*!< 选择时钟源 */
|
||||
uint8_t u8ClockDiv; /*!< 设置时钟分频 */
|
||||
uint8_t u8Mode; /*!< 设置转换模式(8/10/12 bit mode) */
|
||||
uint8_t u8FiFoLevel; /*!< 设置FIFO深度 */
|
||||
} ADC_ConfigType,*ADC_ConfigTypePtr;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC中断.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC中断
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC连续转换.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_ContinuousConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC单次转换
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SingleConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC硬件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHardwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC软件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetSoftwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC比较功能
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC比较功能.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入大于或等于比较电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareGreaterFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入小于比价电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareLessFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为低功耗模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLowPower( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为高速模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHighSpeed( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC长采样.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLongSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC短采样
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetShortSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能FIFO扫描模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用FIFO扫描模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做或运算.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoOr( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做与运算
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoAnd( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对ADC转换结果寄存器.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return ADC result value.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint16_t ADC_ReadResultReg( ADC_Type *pADC )
|
||||
{
|
||||
return (uint16_t)pADC->R;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置比较值.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16Compare 比较值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetCompareValue( ADC_Type *pADC, uint16_t u16Compare )
|
||||
{
|
||||
pADC->CV = u16Compare;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 使能的ADC引脚
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlEnable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 &= ~(0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 禁用的ADC引脚.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlDisable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 |= (0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 查看ADC转换状态
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsConversionActiveFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_ADACT_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取转换完成标准位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsCOCOFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC1 & ADC_SC1_COCO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO中是否有有效新数据标志位
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOEmptyFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FEMPTY_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO是否满标志位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOFullFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FFULL_MASK);
|
||||
}
|
||||
#ifndef CPU_NV32
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Multiple Conversion Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMultiple( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Single Conversion
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerSingle( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Disable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select Automatic Mode
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select to be with HTRGMASKE
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskNonAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Global function
|
||||
******************************************************************************/
|
||||
void ADC_SetChannel( ADC_Type *pADC, uint8_t u8Channel );
|
||||
void ADC_IntEnable( ADC_Type *pADC );
|
||||
void ADC_IntDisable( ADC_Type *pADC );
|
||||
void ADC_ContinuousConversion( ADC_Type *pADC );
|
||||
void ADC_SingleConversion( ADC_Type *pADC );
|
||||
void ADC_SetSoftwareTrigger( ADC_Type *pADC );
|
||||
void ADC_SetHardwareTrigger( ADC_Type *pADC );
|
||||
void ADC_VrefSelect( ADC_Type *pADC, uint8_t u8Vref );
|
||||
void ADC_CompareEnable( ADC_Type *pADC );
|
||||
void ADC_CompareDisable( ADC_Type *pADC );
|
||||
void ADC_CompareGreaterFunction( ADC_Type *pADC );
|
||||
void ADC_CompareLessFunction( ADC_Type *pADC );
|
||||
void ADC_SetLowPower( ADC_Type *pADC );
|
||||
void ADC_SetHighSpeed( ADC_Type *pADC );
|
||||
void ADC_SelectClockDivide( ADC_Type *pADC, uint8_t u8Div);
|
||||
void ADC_SetLongSample(ADC_Type *pADC);
|
||||
void ADC_SetShortSample(ADC_Type *pADC);
|
||||
void ADC_SetMode(ADC_Type *pADC, uint8_t u8Mode);
|
||||
void ADC_SelectClock(ADC_Type *pADC, uint8_t u8Clock);
|
||||
void ADC_FifoScanModeEnable(ADC_Type *pADC);
|
||||
void ADC_FifoScanModeDisable(ADC_Type *pADC);
|
||||
void ADC_CompareFifoOr(ADC_Type *pADC);
|
||||
void ADC_CompareFifoAnd(ADC_Type *pADC);
|
||||
void ADC_SetFifoLevel(ADC_Type *pADC, uint8_t u8FifoLevel);
|
||||
uint16_t ADC_ReadResultReg(ADC_Type *pADC );
|
||||
void ADC_SetCompareValue(ADC_Type *pADC, uint16_t u16Compare );
|
||||
void ADC_PinControlEnable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
void ADC_PinControlDisable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
uint8_t ADC_IsConversionActiveFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsCOCOFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOEmptyFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOFullFlag(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskNonAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerSingle( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMultiple( ADC_Type *pADC );
|
||||
unsigned int ADC_PollRead( ADC_Type *pADC, uint8_t u8Channel);
|
||||
void ADC_SetCallBack(ADC_CallbackType pADC_CallBack);
|
||||
void ADC_DeInit(ADC_Type *pADC);
|
||||
void ADC_Init(ADC_Type *pADC, ADC_ConfigTypePtr pADC_Config);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,655 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ADC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef ADC_H_
|
||||
#define ADC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义ADC参考电压
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_VREF_VREFH 0x00 /*!< ADC 参考电压 VREFH*/
|
||||
#define ADC_VREF_VDDA 0x01 /*!< ADC 参考电压 VDDA*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC时钟源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK 0x00 /*!< ADC时钟源选择总线时钟*/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK_DIVIDE_2 0x01 /*!< ADC时钟源选择总线时钟2分频*/
|
||||
#define CLOCK_SOURCE_ALTCLK 0x02 /*!< ADC时钟源选择备用时钟*/
|
||||
#define CLOCK_SOURCE_ADACK 0x03 /*!< ADC时钟源选择异步时钟*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC源分频系数
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_ADIV_DIVIDE_1 0x00 /*!< ADC时钟源分频系数为1*/
|
||||
#define ADC_ADIV_DIVIDE_2 0x01 /*!< ADC时钟源分频系数为2*/
|
||||
#define ADC_ADIV_DIVIDE_4 0x02 /*!< ADC时钟源分频系数为4*/
|
||||
#define ADC_ADIV_DIVIDE_8 0x03 /*!< ADC时钟源分频系数为8*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_MODE_8BIT 0x00 /*!< 8位转换*/
|
||||
#define ADC_MODE_10BIT 0x01 /*!< 10位转换*/
|
||||
#define ADC_MODE_12BIT 0x02 /*!< 12位转换*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 定义ADC输入通道
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_CHANNEL_AD0 0x0 /*!< ADC输入通道0*/
|
||||
#define ADC_CHANNEL_AD1 0x1 /*!< ADC输入通道1*/
|
||||
#define ADC_CHANNEL_AD2 0x2 /*!< ADC输入通道2*/
|
||||
#define ADC_CHANNEL_AD3 0x3 /*!< ADC输入通道3*/
|
||||
#define ADC_CHANNEL_AD4 0x4 /*!< ADC输入通道4*/
|
||||
#define ADC_CHANNEL_AD5 0x5 /*!< ADC输入通道5*/
|
||||
#define ADC_CHANNEL_AD6 0x6 /*!< ADC输入通道6*/
|
||||
#define ADC_CHANNEL_AD7 0x7 /*!< ADC输入通道7*/
|
||||
#define ADC_CHANNEL_AD8 0x8 /*!< ADC输入通道8*/
|
||||
#define ADC_CHANNEL_AD9 0x9 /*!< ADC输入通道9*/
|
||||
#define ADC_CHANNEL_AD10 0xa /*!< ADC输入通道10*/
|
||||
#define ADC_CHANNEL_AD11 0xb /*!< ADC输入通道11*/
|
||||
#define ADC_CHANNEL_AD12 0xc /*!< ADC输入通道12*/
|
||||
#define ADC_CHANNEL_AD13 0xd /*!< ADC输入通道13*/
|
||||
#define ADC_CHANNEL_AD14 0xe /*!< ADC输入通道14*/
|
||||
#define ADC_CHANNEL_AD15 0xf /*!< ADC输入通道15*/
|
||||
#define ADC_CHANNEL_AD18_VSS 0x12 /*!< ADC输入通道 VSS */
|
||||
#define ADC_CHANNEL_AD22_TEMPSENSOR 0x15 /*!< ADC输入通道温度传感器 */
|
||||
#define ADC_CHANNEL_AD23_BANDGAP 0x17 /*!< ADC输入通道带隙 */
|
||||
#define ADC_CHANNEL_AD29_VREFH 0x1D /*!< ADC输入通道 Vrefh */
|
||||
#define ADC_CHANNEL_AD30_VREFL 0x1E /*!< ADC输入通道 Vrefl */
|
||||
#define ADC_CHANNEL_DISABLE 0x1F /*!< ADC输入通道禁用 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义 ADC FIFO 深度
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_FIFO_DISABLE 0 /*!< FIFO禁用*/
|
||||
#define ADC_FIFO_LEVEL2 1 /*!< 2级FIFO */
|
||||
#define ADC_FIFO_LEVEL3 2 /*!< 3级FIFO */
|
||||
#define ADC_FIFO_LEVEL4 3 /*!< 4级FIFO */
|
||||
#define ADC_FIFO_LEVEL5 4 /*!< 5级FIFO */
|
||||
#define ADC_FIFO_LEVEL6 5 /*!< 6级FIFO */
|
||||
#define ADC_FIFO_LEVEL7 6 /*!< 7级FIFO */
|
||||
#define ADC_FIFO_LEVEL8 7 /*!< 8级FIFO */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换触发源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_HARDWARE_TRIGGER 0x01 /*!< 硬件触发 */
|
||||
#define ADC_SOFTWARE_TRIGGER 0x00 /*!< 软件触发 */
|
||||
#define ADC_TRIGGER_RTC 0x00 /*!< 选择RTC溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_PIT 0x01 /*!< 选择PIT0溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_ETM2INIT 0x10 /*!< 选择ETM2初始化化作为硬件触发源 */
|
||||
#define ADC_TRIGGER_ETM2MATCH 0x11 /*!< 选择ETM2匹配作为硬件触发源 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC比较触发模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_COMPARE_LESS 0x00 /*!< 输入小于比较电平时比较触发*/
|
||||
#define ADC_COMPARE_GREATER 0x01 /*!< 输入大于比价电平时比较触发*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC回调函数声明
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*ADC_CallbackType)(void); /*!< ADC回调函数 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC结构体变量
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bIntEn :1; /*!< 1: 中断使能, 0: 禁用中断 */
|
||||
uint16_t bContinuousEn :1; /*!< 1: 使能连续转换模式, 0: 禁用连续转换模式 */
|
||||
uint16_t bHardwareTriggerEn :1; /*!< 1: 硬件触发, 0: 软件触发 */
|
||||
uint16_t bCompareEn :1; /*!< 1: 使能比较模式, 0: 禁用比较模式 */
|
||||
uint16_t bCompareGreaterEn :1; /*!< 1: 输入大于或等于比较电平时比较触发, 0: 输入小于比较电平时比较触发 */
|
||||
uint16_t bLowPowerEn :1; /*!< 1: 低功耗模式, 0: 高速模式 */
|
||||
uint16_t bLongSampleEn :1; /*!< 1: 长采样模式, 0: 短采样模式 */
|
||||
uint16_t bFiFoScanModeEn :1; /*!< 1: 使能FIFO扫描模式, 0: 禁用FIFO扫描模式 */
|
||||
uint16_t bCompareAndEn :1; /*!< 1: 对所有比较触发做与运算, 0: 对所有比较触发做或运算*/
|
||||
#ifdef CPU_NV32
|
||||
uint16_t bReverse :7;
|
||||
#else
|
||||
uint16_t bHTRGMEn :1; /*!< one hardware trigger pulse trigger multiple conversions in fifo mode */
|
||||
uint16_t bHTRGMASKEn :1; /*!< Hardware trigger mask enable. */
|
||||
uint16_t bHTRGMASKSEL :1; /*!< This field selects hardware trigger mask mode. */
|
||||
uint16_t Reserve :4;
|
||||
#endif
|
||||
} ADC_SettingType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
ADC_SettingType sSetting; /*!< ADC配置结构体*/
|
||||
uint16_t u16PinControl; /*!< 引脚控制 */
|
||||
uint8_t u8ClockSource; /*!< 选择时钟源 */
|
||||
uint8_t u8ClockDiv; /*!< 设置时钟分频 */
|
||||
uint8_t u8Mode; /*!< 设置转换模式(8/10/12 bit mode) */
|
||||
uint8_t u8FiFoLevel; /*!< 设置FIFO深度 */
|
||||
} ADC_ConfigType,*ADC_ConfigTypePtr;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC中断.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC中断
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC连续转换.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_ContinuousConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC单次转换
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SingleConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC硬件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHardwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC软件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetSoftwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC比较功能
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC比较功能.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入大于或等于比较电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareGreaterFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入小于比价电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareLessFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为低功耗模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLowPower( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为高速模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHighSpeed( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC长采样.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLongSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC短采样
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetShortSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能FIFO扫描模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用FIFO扫描模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做或运算.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoOr( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做与运算
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoAnd( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对ADC转换结果寄存器.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return ADC result value.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint16_t ADC_ReadResultReg( ADC_Type *pADC )
|
||||
{
|
||||
return (uint16_t)pADC->R;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置比较值.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16Compare 比较值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetCompareValue( ADC_Type *pADC, uint16_t u16Compare )
|
||||
{
|
||||
pADC->CV = u16Compare;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 使能的ADC引脚
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlEnable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 &= ~(0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 禁用的ADC引脚.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlDisable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 |= (0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 查看ADC转换状态
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsConversionActiveFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_ADACT_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取转换完成标准位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsCOCOFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC1 & ADC_SC1_COCO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO中是否有有效新数据标志位
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOEmptyFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FEMPTY_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO是否满标志位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOFullFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FFULL_MASK);
|
||||
}
|
||||
#ifndef CPU_NV32
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Multiple Conversion Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMultiple( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Single Conversion
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerSingle( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Disable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select Automatic Mode
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select to be with HTRGMASKE
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskNonAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Global function
|
||||
******************************************************************************/
|
||||
void ADC_SetChannel( ADC_Type *pADC, uint8_t u8Channel );
|
||||
void ADC_IntEnable( ADC_Type *pADC );
|
||||
void ADC_IntDisable( ADC_Type *pADC );
|
||||
void ADC_ContinuousConversion( ADC_Type *pADC );
|
||||
void ADC_SingleConversion( ADC_Type *pADC );
|
||||
void ADC_SetSoftwareTrigger( ADC_Type *pADC );
|
||||
void ADC_SetHardwareTrigger( ADC_Type *pADC );
|
||||
void ADC_VrefSelect( ADC_Type *pADC, uint8_t u8Vref );
|
||||
void ADC_CompareEnable( ADC_Type *pADC );
|
||||
void ADC_CompareDisable( ADC_Type *pADC );
|
||||
void ADC_CompareGreaterFunction( ADC_Type *pADC );
|
||||
void ADC_CompareLessFunction( ADC_Type *pADC );
|
||||
void ADC_SetLowPower( ADC_Type *pADC );
|
||||
void ADC_SetHighSpeed( ADC_Type *pADC );
|
||||
void ADC_SelectClockDivide( ADC_Type *pADC, uint8_t u8Div);
|
||||
void ADC_SetLongSample(ADC_Type *pADC);
|
||||
void ADC_SetShortSample(ADC_Type *pADC);
|
||||
void ADC_SetMode(ADC_Type *pADC, uint8_t u8Mode);
|
||||
void ADC_SelectClock(ADC_Type *pADC, uint8_t u8Clock);
|
||||
void ADC_FifoScanModeEnable(ADC_Type *pADC);
|
||||
void ADC_FifoScanModeDisable(ADC_Type *pADC);
|
||||
void ADC_CompareFifoOr(ADC_Type *pADC);
|
||||
void ADC_CompareFifoAnd(ADC_Type *pADC);
|
||||
void ADC_SetFifoLevel(ADC_Type *pADC, uint8_t u8FifoLevel);
|
||||
uint16_t ADC_ReadResultReg(ADC_Type *pADC );
|
||||
void ADC_SetCompareValue(ADC_Type *pADC, uint16_t u16Compare );
|
||||
void ADC_PinControlEnable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
void ADC_PinControlDisable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
uint8_t ADC_IsConversionActiveFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsCOCOFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOEmptyFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOFullFlag(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskNonAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerSingle( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMultiple( ADC_Type *pADC );
|
||||
unsigned int ADC_PollRead( ADC_Type *pADC, uint8_t u8Channel);
|
||||
void ADC_SetCallBack(ADC_CallbackType pADC_CallBack);
|
||||
void ADC_DeInit(ADC_Type *pADC);
|
||||
void ADC_Init(ADC_Type *pADC, ADC_ConfigTypePtr pADC_Config);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @brief Provide Bit-band utilities.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __BIT_BAND_H
|
||||
#define __BIT_BAND_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*//*! @addtogroup BIT_BandType
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief bit band type.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bBit0; /*!< aliase to 0th bit */
|
||||
uint32_t bBit1; /*!< aliase to 1th bit */
|
||||
uint32_t bBit2; /*!< aliase to 2th bit */
|
||||
uint32_t bBit3; /*!< aliase to 3th bit */
|
||||
uint32_t bBit4; /*!< aliase to 4th bit */
|
||||
uint32_t bBit5; /*!< aliase to 5th bit */
|
||||
uint32_t bBit6; /*!< aliase to 6th bit */
|
||||
uint32_t bBit7; /*!< aliase to 7th bit */
|
||||
uint32_t bBit8; /*!< aliase to 8th bit */
|
||||
uint32_t bBit9; /*!< aliase to 9th bit */
|
||||
uint32_t bBit10; /*!< aliase to 10th bit */
|
||||
uint32_t bBit11; /*!< aliase to 11th bit */
|
||||
uint32_t bBit12; /*!< aliase to 12th bit */
|
||||
uint32_t bBit13; /*!< aliase to 13th bit */
|
||||
uint32_t bBit14; /*!< aliase to 14th bit */
|
||||
uint32_t bBit15; /*!< aliase to 15th bit */
|
||||
uint32_t bBit16; /*!< aliase to 16th bit */
|
||||
uint32_t bBit17; /*!< aliase to 17th bit */
|
||||
uint32_t bBit18; /*!< aliase to 18th bit */
|
||||
uint32_t bBit19; /*!< aliase to 19th bit */
|
||||
uint32_t bBit20; /*!< aliase to 20th bit */
|
||||
uint32_t bBit21; /*!< aliase to 21th bit */
|
||||
uint32_t bBit22; /*!< aliase to 22th bit */
|
||||
uint32_t bBit23; /*!< aliase to 23th bit */
|
||||
uint32_t bBit24; /*!< aliase to 24th bit */
|
||||
uint32_t bBit25; /*!< aliase to 25th bit */
|
||||
uint32_t bBit26; /*!< aliase to 26th bit */
|
||||
uint32_t bBit27; /*!< aliase to 27th bit */
|
||||
uint32_t bBit28; /*!< aliase to 28th bit */
|
||||
uint32_t bBit29; /*!< aliase to 29th bit */
|
||||
uint32_t bBit30; /*!< aliase to 30th bit */
|
||||
uint32_t bBit31; /*!< aliase to 31th bit */
|
||||
}BIT_BandType,*BIT_BandPtr;
|
||||
/*! @} End of BIT_BandType */
|
||||
|
||||
/******************************************************************************
|
||||
* define API list
|
||||
*
|
||||
*//*! @addtogroup bit_band_api_list
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief bit-band initialize pointer, so that invoke the pointer to access alisaed bitband.
|
||||
*
|
||||
* @param[in] pVariableAddress - point to variable.
|
||||
* @param[in] pBitbandPtr - point to alisaed bitband address.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void BIT_BandVariableInit( uint32_t *pVariableAddress,BIT_BandPtr *pBitbandPtr )
|
||||
{
|
||||
#if defined(CPU_NV32M3)
|
||||
ASSERT( ((uint32)pVariableAddress >= 0x20000000)&&((uint32_t)pVariableAddress <= 0x200002FF) );
|
||||
#elif defined(CPU_NV32M4)
|
||||
ASSERT( ((uint32)pVariableAddress >= 0x20000000)&&((uint32_t)pVariableAddress <= (0x20000000+12*1024)));
|
||||
#else
|
||||
#error "don't support this function on this device"
|
||||
#endif
|
||||
*pBitbandPtr = (BIT_BandPtr)(((uint32_t)pVariableAddress-0x20000000)*32+0x22000000);
|
||||
}
|
||||
/*! @} End of bit_band_api_list */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __BIT_BAND_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,559 @@
|
||||
/*************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file bos.h
|
||||
* @brief 位操作存储模块(BOS)函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
***************************************************************************/
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __BOS_H
|
||||
#define __BOS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/******************************************************************************
|
||||
*
|
||||
* BOS 操作码(opcode)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define BOS_OPCODE_AND 1 /*!< AND 操作码 */
|
||||
#define BOS_OPCODE_OR 2 /*!< OR 操作码 */
|
||||
#define BOS_OPCODE_XOR 3 /*!< XOR 操作码 */
|
||||
#define BOS_OPCODE_BITFIELD 4 /*!< 位字段操作码 */
|
||||
|
||||
#define BOS_OPCODE_BIT_CLEAR 2 /*!< 位清零操作码 */
|
||||
#define BOS_OPCODE_BIT_SET 3 /*!< 置位操作码 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* BOS宏定义,用来生成BOS硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑与硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑与操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_AND(ADDR) (*(volatile uint32_t *)(((uint32_t)ADDR) | (BOS_OPCODE_AND<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_OR(ADDR) (*(volatile uint32_t *)(((uint32_t)ADDR) | (BOS_OPCODE_OR<<26)))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑异或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_XOR(ADDR) (*(volatile uint32_t *)(((uint32_t)ADDR) | (BOS_OPCODE_XOR<<26)))
|
||||
|
||||
#if !defined(BOS_SANITY_CHECK)
|
||||
/*!
|
||||
* @brief This is fastest way for BOS without sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载清零操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要清零的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BIT_CLEAR(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载置位操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 要置1的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BIT_SET(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作存储字段插入硬件编码地址 (32位硬件编码地址).
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 插入字段的起始位, 0-based.
|
||||
* @param[in] width 插入字段的宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* *宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址 .
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用于生位操作存储加载无符号字段提取(UBFX)操作地址 (32位硬件编码地址).
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 读取起始位, 0-based.
|
||||
* @param[in] width 读取字段宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
#else
|
||||
/*!
|
||||
* @brief This is slow way for BOS as it has sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_CLEAR(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位清零操作 */
|
||||
|
||||
/*****************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_SET(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 置位操作 */
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段插入操作 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段提取操作 */
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* BOS宏定义,用来生成BOS硬件编码地址(8位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.(8位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑与(AND)操作地址(32位硬件编码地址),对8位数据进行与操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_AND_8b(ADDR) (*(volatile uint8_t *)(((uint32_t)ADDR) | (BOS_OPCODE_AND<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或(OR)操作地址(32位硬件编码地址),对8位数据进行或操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_OR_8b(ADDR) (*(volatile uint8_t *)(((uint32_t)ADDR) | (BOS_OPCODE_OR<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑异或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑异或(XOR)操作地址(32位硬件编码地址),对8位数据进行异或操作..
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_XOR_8b(ADDR) (*(volatile uint8_t *)(((uint32_t)ADDR) | (BOS_OPCODE_XOR<<26)))
|
||||
|
||||
#if !defined(BOS_SANITY_CHECK)
|
||||
/*!
|
||||
* @brief This is fastest way for BOS without sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载清零(LAC1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载清零操作地址(32位硬件编码地址)用于8位数据操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要清零的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BIT_CLEAR_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载置1(LAS1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作1位加载置1(LAS1)操作码(32位硬件编码地址)用于8位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要置1的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BIT_SET_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作存储字段插入硬件编码地址 (32位硬件编码地址).用于8位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 插入字段的起始位, 0-based.
|
||||
* @param[in] width 插入字段的宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_INSERT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址 .
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用于生位操作存储加载无符号字段提取(UBFX)操作地址 (32位硬件编码地址).用于8位操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 读取起始位, 0-based.
|
||||
* @param[in] width 读取字段宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BITFIELD_EXTRACT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit<<23) | ((width-1))<<19))
|
||||
#else
|
||||
/*!
|
||||
* @brief This is slow way for BOS as it has sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_CLEAR_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位清零操作,8位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_SET_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位置1操作,8位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段插入操作,8位模式 */
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*******************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_EXTRACT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段提取操作,8位 */
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* BOS宏定义,用来生成BOS硬件编码地址(16位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.(16位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑与(AND)操作地址(32位硬件编码地址),对8位数据进行与操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_AND_16b(ADDR) (*(volatile uint16_t *)(((uint32_t)ADDR) | (BOS_OPCODE_AND<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或(OR)操作地址(32位硬件编码地址),对8位数据进行或操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_OR_16b(ADDR) (*(volatile uint16_t *)(((uint32_t)ADDR) | (BOS_OPCODE_OR<<26)))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑异或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑异或(XOR)操作地址(32位硬件编码地址),对8位数据进行异或操作..
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#define BOS_XOR_16b(ADDR) (*(volatile uint16_t *)(((uint32_t)ADDR) | (BOS_OPCODE_XOR<<26)))
|
||||
|
||||
|
||||
#if !defined(BOS_SANITY_CHECK)
|
||||
/*!
|
||||
* @brief This is fastest way for BOS without sanity check.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载清零(LAC1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载清零操作地址(32位硬件编码地址)用于16位数据操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要清零的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define BOS_BIT_CLEAR_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载置1(LAS1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作1位加载置1(LAS1)操作码(32位硬件编码地址)用于8位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要置1的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BIT_SET_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作存储字段插入硬件编码地址 (32位硬件编码地址).用于16位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 插入字段的起始位, 0-based.
|
||||
* @param[in] width 插入字段的宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_INSERT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址 .
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用于生位操作存储加载无符号字段提取(UBFX)操作地址 (32位硬件编码地址).用于16位操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 读取起始位, 0-based.
|
||||
* @param[in] width 读取字段宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_EXTRACT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
#else
|
||||
/*!
|
||||
* @brief This is slow way for BOS as it has sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_CLEAR_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位清零操作,16位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_SET_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位置1操作,16位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段插入操作,16位模式 */
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_EXTRACT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段提取操作,16位 */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file crc.c
|
||||
* @brief 冗余校验模块(CRC)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "crc.h"
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化CRC
|
||||
*
|
||||
* @param[in] pConfig 指向CRC配置结构体.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void CRC_Init(CRC_ConfigType *pConfig)
|
||||
{
|
||||
uint32_t u32Sc ;
|
||||
|
||||
u32Sc = 0;
|
||||
|
||||
SIM->SCGC |= SIM_SCGC_CRC_MASK; //使能CRC控制模块时钟
|
||||
|
||||
u32Sc |= ((pConfig->bWidth & 0x01)<<24); //CRC模式选择
|
||||
u32Sc |= CRC_CTRL_TOTR(pConfig->bTransposeReadType & 0x03); //设置数据读取的转置类型
|
||||
u32Sc |= CRC_CTRL_TOT(pConfig->bTransposeWriteType & 0x03); //设置数据写入的转置类型
|
||||
|
||||
if (pConfig->bFinalXOR)
|
||||
{
|
||||
u32Sc |= CRC_CTRL_FXOR_MASK; //对CRC数据寄存的读取值进行异或操作
|
||||
}
|
||||
|
||||
CRC0->CTRL = u32Sc;
|
||||
|
||||
if ( pConfig->bWidth )
|
||||
{
|
||||
CRC0->GPOLY = pConfig->u32PolyData; //写入32位多项式
|
||||
}
|
||||
else
|
||||
{
|
||||
CRC0->GPOLY_ACCESS16BIT.GPOLYL = pConfig->u32PolyData; /*!< 仅允许写16位多项式*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 16位模式下CRC计算函数.
|
||||
*
|
||||
* @param[in] seed 种子值
|
||||
* @param[in] msg 指向数据数组
|
||||
* @param[in] sizeBytes 数据大小
|
||||
*
|
||||
* @return data_out convertion result
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t CRC_Cal16(uint32_t seed, uint8_t *msg, uint32_t sizeBytes)
|
||||
{
|
||||
uint32_t ctrl_reg,data_out,data_in;
|
||||
uint8_t *pCRCBytes;
|
||||
uint32_t sizeWords;
|
||||
uint32_t i,j;
|
||||
|
||||
/* 设置WaS=1,写入种子值 */
|
||||
ctrl_reg = CRC0->CTRL;
|
||||
CRC0->CTRL = ctrl_reg | CRC_CTRL_WAS_MASK;
|
||||
CRC0->ACCESS16BIT.DATAL = seed;
|
||||
|
||||
/* Set WaS=0,准备写入数据*/
|
||||
CRC0->CTRL = ctrl_reg & 0xFD000000;
|
||||
|
||||
/*等待计算完成*/
|
||||
sizeWords = sizeBytes>>1;
|
||||
j = 0;
|
||||
for(i=0;i<sizeWords;i++){
|
||||
data_in = (msg[j] << 8) | (msg[j+1]); /*将数据写入CRC数据寄存器,以16位方式写入*/
|
||||
j += 2;
|
||||
CRC0->ACCESS16BIT.DATAL =data_in;
|
||||
}
|
||||
if (j<sizeBytes)
|
||||
{
|
||||
pCRCBytes = (uint8_t*)&CRC0->ACCESS8BIT.DATALL; /*以8位的方式写入剩余的数据*/
|
||||
*pCRCBytes++ = msg[j];
|
||||
}
|
||||
if ((CRC0->CTRL& CRC_CTRL_TOTR_MASK)>1) //Modify
|
||||
{
|
||||
data_out=CRC0->ACCESS16BIT.DATAH; //读出字节转置后16位计算结果
|
||||
}
|
||||
else
|
||||
{
|
||||
data_out=CRC0->ACCESS16BIT.DATAL; //读出16位计算结果
|
||||
}
|
||||
|
||||
return(data_out);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 32位模式下CRC计算.
|
||||
*
|
||||
* @param[in] seed
|
||||
* @param[in] msg 指向数据数组
|
||||
* @param[in] sizeBytes 数据大小
|
||||
*
|
||||
* @return data_out convertion result
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t CRC_Cal32(uint32_t seed, uint8_t *msg, uint32_t sizeBytes)
|
||||
{
|
||||
uint32_t ctrl_reg,data_out,data_in;
|
||||
uint32_t sizeDwords;
|
||||
uint8_t *pCRCBytes;
|
||||
uint32_t i,j;
|
||||
|
||||
/* 设置WaS=1,写入种子值 */
|
||||
ctrl_reg = CRC0->CTRL;
|
||||
CRC0->CTRL = ctrl_reg | 0x02000000;
|
||||
CRC0->DATA = seed;
|
||||
|
||||
/* Set WaS=0,准备写入数据*/
|
||||
CRC0->CTRL = ctrl_reg & 0xFD000000;
|
||||
|
||||
/*等待数据计算完成*/
|
||||
sizeDwords = sizeBytes>>2;
|
||||
j = 0;
|
||||
for(i=0;i<sizeDwords;i++)
|
||||
{
|
||||
data_in = ((msg[j] << 24) | (msg[j+1] << 16) | (msg[j+2] << 8) | msg[j+3]); /*将数据写入CRC数据寄存器,以32方式写入*/
|
||||
j += 4;
|
||||
CRC0->DATA = data_in;
|
||||
}
|
||||
if (j<sizeBytes)
|
||||
{
|
||||
pCRCBytes = (uint8_t*)&CRC0->ACCESS8BIT.DATALL; /*以8位的方式写入剩余的数据*/
|
||||
|
||||
#if defined(BYTE_ENABLES_1_2_4_8)
|
||||
|
||||
/*只写单个字节*/
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
*pCRCBytes++ = msg[j];
|
||||
}
|
||||
#elif defined(BYTE_ENABLES_3_6_C)
|
||||
|
||||
/*写入两个字节*/
|
||||
data_in = 0;
|
||||
i = 0;
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
data_in = (data_in <<8) | msg[j];
|
||||
i++;
|
||||
if (i==2)
|
||||
{
|
||||
i = 0;
|
||||
CRC0->ACCESS16BIT.DATAL = data_in;
|
||||
}
|
||||
}
|
||||
if (i==1)
|
||||
{
|
||||
CRC0->ACCESS8BIT.DATALL = data_in; /*!< 写入最后一个字节 */
|
||||
}
|
||||
#elif defined(BYTE_ENABLES_7_E)
|
||||
/*!< 写入三个字节*/
|
||||
data_in = 0;
|
||||
i = 0;
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
data_in = (data_in <<8) | msg[j];
|
||||
i++;
|
||||
if (i==3)
|
||||
{
|
||||
i = 0;
|
||||
/*写入第一个字符*/
|
||||
CRC0->ACCESS8BIT.DATAHL = (data_in>>16) & 0xff; /*!< 写入高字的低字节 */
|
||||
/*写入最后两个字节*/
|
||||
CRC0->ACCESS16BIT.DATAL = data_in & 0x00ffff; /*!< 写入低字 */
|
||||
}
|
||||
}
|
||||
if ( i == 2)
|
||||
{
|
||||
CRC0->ACCESS16BIT.DATAL = (data_in); /*!< 写最后两个字节 */
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
CRC0->ACCESS8BIT.DATALL = data_in; /*!< 写最后一个字节 */
|
||||
}
|
||||
#else /*!< 只写低字节 */
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
*pCRCBytes = msg[j];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
data_out=CRC0->DATA;
|
||||
|
||||
return(data_out); //读出32位计算结果
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位CRC模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void CRC_DeInit(void)
|
||||
{
|
||||
CRC0->CTRL = 0x3000000; /*!<设置CRC位32位模式*/
|
||||
CRC0->DATA = 0xFFFFFFFF;/*!< 写32位种子值到CRC数据寄存器*/
|
||||
while(!(CRC0->DATA == 0xFFFFFFFF));
|
||||
CRC0->GPOLY = 0x00001021;
|
||||
CRC0->CTRL = 0; /*!<CRC控制寄存器清零*/
|
||||
SIM->SCGC &= ~SIM_SCGC_CRC_MASK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief CRC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef CRC_H_
|
||||
#define CRC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/**********************************************************************!
|
||||
* @brief CRC控制寄存器位定义
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#define CRC_WIDTH_16BIT 0 /*!< 选择16位CRC协议 */
|
||||
#define CRC_WIDTH_32BIT 1 /*!< 选择32位CRC协议 */
|
||||
#define CRC_DATA_SEED 1 /*!< 写入CRC数据寄存器的值为种子值 */
|
||||
#define CRC_DATA_DATA 0 /*!< 写入CRC数据寄存器的值为数据值 */
|
||||
#define CRC_READ_COMPLETE 1 /*!< 反转或补充CRC数据寄存器的读取值 */
|
||||
#define CRC_READ_NONE 0 /*!< 读取数据寄存器时不执行异或运算*/
|
||||
#define CRC_READ_TRANSPOSE_NONE 0 /*!< 读取数据寄存器的值无转置 */
|
||||
#define CRC_READ_TRANSPOSE_BIT 1 /*!< 读取数据寄存器的值,字节中的位转置,字不转置*/
|
||||
#define CRC_READ_TRANSPOSE_ALL 2 /*!< 读取数据寄存器的值,字节中的位和字节均转置 */
|
||||
#define CRC_READ_TRANSPOSE_BYTE 3 /*!< 读取数据寄存器的值,仅字节转置,字节中的位不转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_NONE 0 /*!< 写数据时无转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_BIT 1 /*!< 写数据时,字节中的位转置,字节不转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_ALL 2 /*!< 写数据时,字节中的位和字节均转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_BYTE 3 /*!< 写数据时,仅字节转置,字节中的位不转置 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* CRC 配置结构体类型.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bWidth : 1; /*!< 1: 32位CRC协议 0: 16位CRC协议 */
|
||||
uint8_t bDataType : 1; /*!< 1: 写入种子值 , 0: 写入数据 */
|
||||
uint8_t bFinalXOR : 1; /*!< 1: 读数据是反转或补充 , 0: 读数据时不执行异或*/
|
||||
uint8_t bRESERVED : 1; /*!< 保留位 */
|
||||
uint8_t bTransposeReadType : 2; /*!< 读取数据时的转置类型, 参阅参考手册 */
|
||||
uint8_t bTransposeWriteType : 2; /*!< 写数据时的转置类型, 参阅参考手册 */
|
||||
uint32_t u32PolyData ; /*!< 32位或16位多项式*/
|
||||
} CRC_ConfigType, *CRC_ConfigPtr ;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void CRC_Init(CRC_ConfigType *pConfig);
|
||||
uint32_t CRC_Cal16(uint32_t u32Seed, uint8_t *msg, uint32_t u32SizeBytes);
|
||||
uint32_t CRC_Cal32(uint32_t u32Seed, uint8_t *msg, uint32_t u32SizeBytes);
|
||||
void CRC_DeInit(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/***********************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file delay.c
|
||||
* @brief systic函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
************************************************************************/
|
||||
#include "delay.h"
|
||||
|
||||
//延时驱动C 文件
|
||||
|
||||
/***********************************************************************************************
|
||||
功能:初始化延时模块
|
||||
形参:0
|
||||
返回:0
|
||||
详解:此函数用于初始化延时模块,使用函数时必须调用。否则会造成延时函数出错
|
||||
************************************************************************************************/
|
||||
void DelayInit(void)
|
||||
{
|
||||
SysTick->CTRL = 0;//选取systick的时钟为内核时钟/16
|
||||
}
|
||||
/***********************************************************************************************
|
||||
功能:US级延时函数
|
||||
形参:US 需要延时多少US
|
||||
返回:0
|
||||
详解:裸机下的延时US
|
||||
************************************************************************************************/
|
||||
void DelayUs(uint32_t us)
|
||||
{
|
||||
uint32_t temp;
|
||||
SysTick->LOAD = (us*BUS_CLK_HZ/10000)/(1600); //时间加载
|
||||
SysTick->VAL = 0x00; //清空计数器
|
||||
SysTick->CTRL |= 0x01 ; //开始倒数
|
||||
do
|
||||
{
|
||||
temp = SysTick->CTRL;
|
||||
}while(temp & 0x01 && !(temp & (1<<16))); //等待时间到达
|
||||
SysTick->CTRL &= ~0x01; //关闭计数器
|
||||
}
|
||||
/***********************************************************************************************
|
||||
功能:MS级延时函数
|
||||
形参:MS需要延时多少MS
|
||||
返回:0
|
||||
详解:裸机下的延时MS
|
||||
************************************************************************************************/
|
||||
void DelayMs(uint32_t ms)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint16_t i;
|
||||
for(i = 0;i < ms;i++) //延时 MS
|
||||
{
|
||||
SysTick->LOAD = (BUS_CLK_HZ/1000)/16; //时间加载1ms
|
||||
SysTick->VAL = 0x00; //清空计数器
|
||||
SysTick->CTRL |= 0x01; //开始倒数
|
||||
do
|
||||
{
|
||||
temp = SysTick->CTRL;
|
||||
}while(temp & 0x01 && !(temp & (1<<16))); //等待时间到达
|
||||
SysTick->CTRL &= ~0x01; //关闭计数器
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef __DELAY_H__
|
||||
#define __DELAY_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "sysinit.h"
|
||||
#include "common.h"
|
||||
#include "core_cm0plus.h"
|
||||
//本构件实现的接口函数列表
|
||||
void DelayInit(void); //延时初始化
|
||||
void DelayUs(uint32_t us); //延时us
|
||||
void DelayMs(uint32_t ms); //延时ms
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,270 @@
|
||||
/*****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file eeprom.c
|
||||
* @brief flash模拟eeprom库函数
|
||||
* @author Navota
|
||||
* @date 2018-1-1
|
||||
***************************************************************************/
|
||||
#include "flash.h"
|
||||
#include "eeprom.h"
|
||||
#include <string.h>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 擦除命令,擦掉eeprom
|
||||
*输入参数:地址,函数将会擦除adr所在的扇区(512字节)
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t Adress_Js(uint32_t adr)
|
||||
{
|
||||
uint16_t err = EEPROM_ERR_SUCCESS;
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 擦除命令,擦掉eeprom
|
||||
*输入参数:地址,函数将会擦除adr所在的512bytes eeprom
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t EEPROM_Erase(uint32_t adr)
|
||||
{
|
||||
uint16_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t e_adr;
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
err = Flash_EraseSector(e_adr);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 读取函数,读取地址所在的eeprom
|
||||
*输入参数:地址
|
||||
*
|
||||
******************************************************************************/
|
||||
uint32_t EEPROM_Read(uint32_t adr)
|
||||
{
|
||||
uint16_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t e_adr;
|
||||
uint32_t data;
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
data = M32(e_adr);
|
||||
return (data);
|
||||
}
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 写函数,写地址所在的eeprom
|
||||
* 写之前读取出来,判断eeprom是否为空,如果为空,则直接写
|
||||
* 如果非空,则先把整个512bytes sector读取到sram,修改要写的位置
|
||||
* 然后再写入到flash,模拟一个eeprom的写过程
|
||||
* 输入参数:地址
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t EEPROM_Write(uint32_t adr, uint32_t Data)
|
||||
{
|
||||
|
||||
uint32_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t e_adr;
|
||||
uint32_t r_data;
|
||||
uint16_t i;
|
||||
uint32_t start_adr;
|
||||
// uint32_t modify_adr;
|
||||
uint32_t EEPROM_DATA[128];
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
|
||||
r_data = EEPROM_Read(adr);
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
|
||||
if (r_data == EEPROM_BLANK) //如果要写的位置是空的,则直接写
|
||||
{
|
||||
err = Flash_Program1LongWord(e_adr, Data);
|
||||
}
|
||||
else if ((r_data & Data) == Data) //如果要写的位置对应的bit,和要写的数据一致,或者是1,也是可以直接写
|
||||
{
|
||||
err = Flash_Program1LongWord(e_adr, Data);
|
||||
}
|
||||
else if (r_data == Data) //如果要写的数据和现有的数据一致,就不进行任何操作,直接返回
|
||||
{
|
||||
return (err);
|
||||
}
|
||||
else
|
||||
{
|
||||
start_adr = e_adr & EEPROM_SECTOR_MASK; //计算出sector的头地址
|
||||
|
||||
for (i = 0; i < 128; i++) //如果要写的位置不为空,则先把flash内容读取出来,放在sram中,修改
|
||||
{
|
||||
EEPROM_DATA[i] = M32(start_adr + 4 * i);
|
||||
}
|
||||
|
||||
EEPROM_DATA[(adr & EEPROM_ARRAY_ADR_MASK) >> 2] = Data; //修改SRAM 中的数据
|
||||
|
||||
err = EEPROM_Erase(adr);
|
||||
|
||||
err = Flash_Program(start_adr, (uint8_t *)EEPROM_DATA, 512); //然后写入flash
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*Byte 写函数
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t EEPROM_WriteByte(uint32_t adr, uint8_t Data)
|
||||
{
|
||||
uint32_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t data_mask;
|
||||
uint32_t r_data;
|
||||
uint32_t data_m0;
|
||||
uint32_t data_m1;
|
||||
uint32_t word_adr = adr & 0x3fc;
|
||||
uint32_t b_sit = adr & 0x3;
|
||||
|
||||
//先让高位为FF
|
||||
data_m0 = Data << b_sit * 8;
|
||||
data_mask = 0xFFFFFFFF << (b_sit + 1) * 8;
|
||||
//然后让低位为FF
|
||||
data_m1 = 0xFFFFFFFF >> (32 - b_sit * 8);
|
||||
data_m1 = data_m1 | data_m0 | data_mask;
|
||||
|
||||
r_data = EEPROM_Read(word_adr);
|
||||
r_data |= 0xFF << b_sit * 8;
|
||||
|
||||
data_m1 = data_m1 & r_data;
|
||||
|
||||
err = EEPROM_Write(word_adr, data_m1);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*Byte 读函数
|
||||
*
|
||||
******************************************************************************/
|
||||
uint8_t EEPROM_ReadByte(uint32_t adr)
|
||||
{
|
||||
uint32_t r_data;
|
||||
uint32_t word_adr = adr & 0x3fc;
|
||||
uint32_t b_sit = adr & 0x3;
|
||||
uint8_t data;
|
||||
|
||||
r_data = EEPROM_Read(word_adr);
|
||||
data = (r_data >> b_sit * 8) & 0xff;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*写函数,写一个长度为bytesize,到eeprom
|
||||
*先把1k的eeprom读取放入sram,然后修改要写的位置,
|
||||
*这个函数是还可以再优化的
|
||||
******************************************************************************/
|
||||
uint16_t EERPOM_Writeup4byte(uint32_t adr, uint8_t *pData, uint32_t length)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *pbuf;
|
||||
uint32_t e_adr;
|
||||
uint32_t e_sec;
|
||||
uint32_t e_offset;
|
||||
uint32_t a;
|
||||
uint32_t err = EEPROM_ERR_SUCCESS;
|
||||
|
||||
#ifdef IAR
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((adr + length) > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
e_sec = e_adr & EEPROM_SECTOR_MASK;
|
||||
e_offset = e_adr & 0x1ff;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
//如果起始地址不等于0,或者长度小于512 都进入这个循环
|
||||
if (e_offset || (length < 512))
|
||||
{
|
||||
pbuf = buf;
|
||||
a = 512 - e_offset;
|
||||
a = (length > a ? a : length);
|
||||
|
||||
memcpy(buf, (uint8_t *)e_sec, 512);
|
||||
memcpy(&buf[e_offset], pData, a);
|
||||
pData += a;
|
||||
length -= a;
|
||||
e_offset = 0;
|
||||
}
|
||||
else
|
||||
{ //如果起始地址等于0且长度大于512
|
||||
pbuf = pData;
|
||||
pData += 512;
|
||||
length -= 512;
|
||||
}
|
||||
err = Flash_EraseSector(e_sec);
|
||||
err = Flash_Program(e_sec, (uint8_t *)pbuf, 512); //然后写入flash
|
||||
e_sec += 0x200;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief eeprom Çý¶¯Í·Îļþ.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef EEPROM_H_
|
||||
#define EEPROM_H_
|
||||
|
||||
/******************************************************************************
|
||||
* Includes
|
||||
******************************************************************************/
|
||||
#include "common.h"
|
||||
|
||||
#define EERPOM_SIZE 1024 // in bytes
|
||||
#define EEPROM_START_ADR 0x00401000
|
||||
#define EEPROM_ERR_SUCCESS 0x01
|
||||
#define EEPROM_ADR_OverFlow 0x02
|
||||
#define EEPROM_ERR_INVALID_PARAM 0x04
|
||||
#define EEPROM_BLANK 0xffffffff
|
||||
#define EEPROM_SECTOR_MASK 0x00401200
|
||||
#define EEPROM_ARRAY_ADR_MASK 0x1ff
|
||||
|
||||
|
||||
uint16_t Adress_Js(uint32_t adr);
|
||||
uint16_t EEPROM_Erase(uint32_t adr);
|
||||
uint32_t EEPROM_Read(uint32_t adr);
|
||||
uint8_t EEPROM_ReadByte(uint32_t adr);
|
||||
|
||||
|
||||
uint16_t EEPROM_Write(uint32_t adr, uint32_t Data);
|
||||
uint16_t EEPROM_WriteByte(uint32_t adr, uint8_t Data);
|
||||
uint16_t EERPOM_Writeup4byte(uint32_t adr, uint8_t *pData,uint32_t length);
|
||||
#endif
|
||||
@@ -0,0 +1,852 @@
|
||||
/*****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file etm.c
|
||||
* @brief etm定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
***************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "etm.h"
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
ETM_CallbackPtr ETM_Callback[3] = {(ETM_CallbackPtr)NULL};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 定义ETM的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM模块时钟资源及分频系数.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] ClockSource ETM 选择的时钟源 : 禁用(ETM_CLOCK_NOCLOCK)、系统时钟(ETM_CLOCK_SYSTEMCLOCK)、固定频率时钟/2(ETM_CLOCK_FIXEDFREQCLOCK)、外接时钟(ETM_CLOCK_EXTERNALCLOCK).
|
||||
* @param[in] ClockPrescale 分频系数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_ClockSet(ETM_Type *pETM, uint8_t u8ClockSource, uint8_t u8ClockPrescale)
|
||||
{
|
||||
uint8_t u8Temp;
|
||||
u8Temp = (pETM->SC & 0xE0);//pETM指向的SC寄存器低5位清0,即未选择时钟,时钟输入采取1分频
|
||||
u8Temp |= (ETM_SC_CLKS(u8ClockSource & 0x3) | ETM_SC_PS(u8ClockPrescale & 0x7));
|
||||
pETM->SC = u8Temp;//配置该ETM的状态与控制寄存器ETMx_SC
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM中PWM的初始化函数
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] PWMModeSelect 居中对齐CPWM(10)、边沿对齐EPWM(01)以及级联模式PWM(11).
|
||||
* @param[in] PWMEdgeSelect 高真脉冲(01)、低真脉冲(10).
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_PWMInit(ETM_Type *pETM, uint8_t u8PWMModeSelect, uint8_t u8PWMEdgeSelect)
|
||||
{
|
||||
uint8_t channels, i;
|
||||
|
||||
ASSERT((ETM0== pETM) || (ETM1== pETM) || (ETM2== pETM));//断言来检测ETM通道是否正确
|
||||
|
||||
/* 选用ETM时钟 */
|
||||
if (ETM0 == pETM)
|
||||
{
|
||||
channels = 2;
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK; //ETM0共有两个通道
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
channels = 2;
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK; //ETM1共有两个通道
|
||||
}
|
||||
else
|
||||
{
|
||||
channels = 6;
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK; //ETM2共有六个通道
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; //关闭计数器
|
||||
pETM->MOD = ETM_MOD_INIT;
|
||||
|
||||
if(ETM_PWMMODE_CENTERALLIGNED == u8PWMModeSelect) //打开CPWM
|
||||
{
|
||||
pETM->SC |= ETM_SC_CPWMS_MASK;
|
||||
}
|
||||
else if(ETM_PWMMODE_COMBINE == u8PWMModeSelect)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
pETM->MODE |= ETM_MODE_WPDIS_MASK | ETM_MODE_ETMEN_MASK;
|
||||
pETM->COMBINE = ETM_COMBINE_COMBINE0_MASK | ETM_COMBINE_COMP0_MASK | ETM_COMBINE_SYNCEN0_MASK | ETM_COMBINE_DTEN0_MASK |
|
||||
ETM_COMBINE_COMBINE1_MASK | ETM_COMBINE_COMP1_MASK | ETM_COMBINE_SYNCEN1_MASK | ETM_COMBINE_DTEN1_MASK |
|
||||
ETM_COMBINE_COMBINE2_MASK | ETM_COMBINE_COMP2_MASK | ETM_COMBINE_SYNCEN2_MASK | ETM_COMBINE_DTEN2_MASK
|
||||
; // 打开通道级联模式
|
||||
pETM->SC &= ~ETM_SC_CPWMS_MASK;
|
||||
}
|
||||
if(ETM_PWM_HIGHTRUEPULSE == u8PWMEdgeSelect)
|
||||
{
|
||||
/* 配置通道寄存器,设置通道状态及通道计数值 */
|
||||
for(i=0; i<channels; i++)
|
||||
{
|
||||
pETM->CONTROLS[i].CnSC = ETM_CnSC_MSB_MASK | ETM_CnSC_ELSB_MASK;
|
||||
pETM->CONTROLS[i].CnV = ETM_C0V_INIT + i*100;
|
||||
}
|
||||
}
|
||||
else if(ETM_PWM_LOWTRUEPULSE == u8PWMEdgeSelect)
|
||||
{
|
||||
for(i=0; i<channels; i++)
|
||||
{
|
||||
pETM->CONTROLS[i].CnSC = ETM_CnSC_MSB_MASK | ETM_CnSC_ELSA_MASK;
|
||||
pETM->CONTROLS[i].CnV = ETM_C0V_INIT + i*100 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ETM的通道功能,用于GPIO或其他功能
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] u8ETM_Channel 通道号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
void ETM_disblechannel(ETM_Type *pETM, uint8_t u8ETM_Channel)
|
||||
{
|
||||
uint8_t i;
|
||||
i= u8ETM_Channel;
|
||||
pETM->CONTROLS[i].CnSC &= ~ (ETM_CnSC_ELSB_MASK| ETM_CnSC_ELSA_MASK);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 输入捕捉初始化函数.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] Channel 配置通道号.
|
||||
* @param[in] CaptureMode 选择捕捉方式:上升沿, 下降沿或跳变沿.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_InputCaptureInit(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8CaptureMode)
|
||||
{
|
||||
ASSERT(((ETM0 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM1 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM2 == pETM) && (u8ETM_Channel < 6))
|
||||
);
|
||||
|
||||
|
||||
/* 选用ETM时钟 */
|
||||
if ((ETM0 == pETM) && (u8ETM_Channel < 2))
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
NVIC_EnableIRQ(ETM0_IRQn);
|
||||
}
|
||||
else if((ETM1 == pETM) && (u8ETM_Channel < 2))
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
NVIC_EnableIRQ(ETM1_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
NVIC_EnableIRQ(ETM2_IRQn);
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; //关闭计数器
|
||||
pETM->MOD = 0xFFFF;
|
||||
|
||||
if(ETM_INPUTCAPTURE_RISINGEDGE == u8CaptureMode) //开启中断,捕获上升沿
|
||||
{
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = ETM_CnSC_CHIE_MASK | ETM_CnSC_ELSA_MASK;
|
||||
}
|
||||
else if(ETM_INPUTCAPTURE_FALLINGEDGE == u8CaptureMode) //捕获下降沿
|
||||
{
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = ETM_CnSC_CHIE_MASK | ETM_CnSC_ELSB_MASK;
|
||||
}
|
||||
else if(ETM_INPUTCAPTURE_BOTHEDGE == u8CaptureMode) //捕获跳变沿
|
||||
{
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = ETM_CnSC_CHIE_MASK | ETM_CnSC_ELSA_MASK | ETM_CnSC_ELSB_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 对ETM配置双边捕获模式来测量一个脉冲的宽度或周期(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] ChannelPair 频道配对数的配置为: 0, 2, 4.
|
||||
* @param[in] CaptureMode 选择单周期捕捉(4),和连续捕捉方式(5).
|
||||
* @param[in] Channel_N_Edge 频道N边沿检测:无(0),上升沿(1)下降沿(2)双沿(3).
|
||||
* @param[in] Channel_Np1_Edge 频道N+1边沿检测.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_DualEdgeCaptureInit(ETM_Type *pETM, uint8_t u8ChannelPair, uint8_t u8CaptureMode,
|
||||
uint8_t u8Channel_N_Edge, uint8_t u8Channel_Np1_Edge)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ChannelPair < 6) && !(u8ChannelPair & 1) );
|
||||
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
if((0 == u8ChannelPair) || (2== u8ChannelPair))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; /* 关闭计数器 */
|
||||
pETM->MOD = 0xFFFF;
|
||||
pETM->MODE |= ETM_MODE_ETMEN_MASK; /* ETMEN = 1 */
|
||||
|
||||
pETM->COMBINE |= ((ETM_COMBINE_DECAPEN0_MASK) << (u8ChannelPair * 4));
|
||||
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC &= ~ETM_CnSC_CHF_MASK; /* CH(n)F 和 CH(n+1)F 位必须要先清除 */
|
||||
pETM->CONTROLS[u8ChannelPair + 1].CnSC &= ~ETM_CnSC_CHF_MASK;
|
||||
|
||||
if(ETM_INPUTCAPTURE_DUALEDGE_ONESHOT == u8CaptureMode) /* 单次模式 */
|
||||
{
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC &= ~ETM_CnSC_MSA_MASK;
|
||||
pETM->CONTROLS[u8ChannelPair+1].CnSC &= ~ETM_CnSC_MSA_MASK;
|
||||
}
|
||||
else if(ETM_INPUTCAPTURE_DUALEDGE_CONTINUOUS == u8CaptureMode) /* 连续模式 */
|
||||
{
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC |= ETM_CnSC_MSA_MASK;
|
||||
pETM->CONTROLS[u8ChannelPair+1].CnSC |= ETM_CnSC_MSA_MASK;
|
||||
}
|
||||
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC |= (u8Channel_N_Edge << 2); /* 选择检测边沿 */
|
||||
pETM->CONTROLS[u8ChannelPair + 1].CnSC |= (u8Channel_Np1_Edge << 2);
|
||||
|
||||
pETM->COMBINE |= (ETM_COMBINE_DECAP0_MASK << (u8ChannelPair * 4));
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 输出对比初始化.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] Channel 配置通道即通道号.
|
||||
* @param[in] CompareMode 选择模式:翻转(01)、置位(11)、清0(10).
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_OutputCompareInit(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8CompareMode)
|
||||
{
|
||||
ASSERT(((ETM0 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM1 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM2 == pETM) && (u8ETM_Channel < 6))
|
||||
);
|
||||
|
||||
/* 选用ETM模块时钟 */
|
||||
if(ETM0 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; //关闭计数器
|
||||
pETM->MOD = ETM_MOD_INIT;
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = (ETM_CnSC_MSA_MASK | (u8CompareMode << 2));
|
||||
pETM->CONTROLS[u8ETM_Channel].CnV = ETM_C0V_INIT;
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 实现软件同步触发(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SoftwareSync(ETM_Type *pETM)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM中配置ETMx_SYNC 寄存器来选择硬件触发(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8TriggerN 选择硬件触发资源.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_HardwareSync(ETM_Type *pETM, uint8_t u8TriggerN)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
|
||||
switch(u8TriggerN)
|
||||
{
|
||||
case ETM_SYNC_TRIGGER_TRIGGER2:
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
break;
|
||||
case ETM_SYNC_TRIGGER_TRIGGER1:
|
||||
pETM->SYNC |= ETM_SYNC_TRIG1_MASK;
|
||||
break; /* 需要先配置ETM0CH0 */
|
||||
case ETM_SYNC_TRIGGER_TRIGGER0:
|
||||
pETM->SYNC |= ETM_SYNC_TRIG0_MASK;
|
||||
break; /* 需要先配置ACMP0 */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 通过配置ETM保证硬件同步,产生触发(可有多个触发)(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8TriggerMask 硬件触发资源标志号.联合TRIG0~TREG2.(x000xxxx~x111xxxx)
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_HardwareSyncCombine(ETM_Type *pETM, uint8_t u8TriggerMask)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
pETM->SYNC &= 0x8F;
|
||||
pETM->SYNC |= (u8TriggerMask & 0x70);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 硬件触发2产生ETM2的PWM同步触发(ETM2)
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_GenerateTrig2(ETM_Type *pETM)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
if(pETM->SYNC & ETM_SYNC_TRIG2_MASK)
|
||||
{
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM死区时间设置(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] PrescalerValue 总线时钟分频值, 0 to 3.
|
||||
* @param[in] DeadETMeValue 时钟数值插入, 0 to 63.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_PWMDeadETMeSet(ETM_Type *pETM, uint8_t u8PrescalerValue, uint8_t u8DeadETMeValue)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->COMBINE |= 0x101010; /* 使能死区时间插入 */
|
||||
|
||||
if(!(pETM->MODE & ETM_MODE_WPDIS_MASK)) /* 判断是否使能写保护 */
|
||||
{
|
||||
pETM->MODE |= ETM_MODE_WPDIS_MASK; /* 禁止写保护 */
|
||||
pETM->DEADETME = (ETM_DEADETME_DTVAL(u8DeadETMeValue & 0x3F) | ETM_DEADETME_DTPS(u8PrescalerValue & 0x3));
|
||||
pETM->MODE &= ~ETM_MODE_WPDIS_MASK; /* 使能写保护 */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 若无写保护 */
|
||||
pETM->DEADETME = (ETM_DEADETME_DTVAL(u8DeadETMeValue & 0x3F) | ETM_DEADETME_DTPS(u8PrescalerValue & 0x3));
|
||||
}
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK; /* 设置软件同步 */
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 设置输出屏蔽(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] Channel 需要屏蔽的通道号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_OutputMaskSet(ETM_Type *pETM, uint8_t u8ETM_Channel)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ETM_Channel < 6));
|
||||
|
||||
pETM->OUTMASK |= (1 << u8ETM_Channel);
|
||||
|
||||
if(pETM->SYNC & ETM_SYNC_SYNCHOM_MASK) /* 通过PWM同步更新 */
|
||||
{
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWOM_MASK) /* 软件触发激活 */
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
else if(pETM->SYNCONF & ETM_SYNCONF_HWOM_MASK) /* 硬件触发激活 */
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK; /* 使能硬件同步 */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
else /* 若无软件同步, 在系统时钟的上升沿对其更新 */
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 配置软件输出控制SWOCTRL寄存器的同步是否由软件触发(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] Channel 软件触发PWM波的通道选择.
|
||||
* @param[in] ChannelValue 0或1,0不触发;1触发.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SWOutputControlSet(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8ChannelValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ETM_Channel < 6));
|
||||
|
||||
if(ETM_SWOCTRL_HIGH == u8ChannelValue)
|
||||
{
|
||||
pETM->SWOCTRL |= (0x0101 << u8ETM_Channel);
|
||||
}
|
||||
else if(ETM_SWOCTRL_LOW == u8ChannelValue)
|
||||
{
|
||||
pETM->SWOCTRL |= (1 << u8ETM_Channel);
|
||||
pETM->SWOCTRL &= ~(0x100 << u8ETM_Channel);
|
||||
}
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWOC_MASK)
|
||||
{
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWSOC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
else if(pETM->SYNCONF & ETM_SYNCONF_HWSOC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 设置通道输出极性(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] Channel PWM波的通道选择.
|
||||
* @param[in] ActiveValue 极性的选择,0为高电平,1为低电平.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_PolaritySet(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8ActiveValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ETM_Channel < 6));
|
||||
|
||||
if(ETM_POLARITY_HIGHACTIVE == u8ActiveValue)
|
||||
{
|
||||
pETM->POL &= ~(1 << u8ETM_Channel);
|
||||
}
|
||||
else if(ETM_POLARITY_LOWACTIVE == u8ActiveValue)
|
||||
{
|
||||
pETM->POL |= (1 << u8ETM_Channel);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM模块在debug模式下的行为(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8DebugMode debug 的模式从00-11之间选择.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SetDebugModeBehavior(ETM_Type *pETM, uint8_t u8DebugMode)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->CONF &= ~ETM_CONF_BDMMODE_MASK;
|
||||
pETM->CONF |= ETM_CONF_BDMMODE(u8DebugMode);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM中TOF频率大小的设置(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8TOFNUM TOF频率数,大小0和31之间.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SetTOFFrequency(ETM_Type *pETM, uint8_t u8TOFNUM)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->CONF &= ~ETM_CONF_NUMTOF_MASK;
|
||||
pETM->CONF |= ETM_CONF_NUMTOF(u8TOFNUM);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 交换通道CH(n)和通道CH(n+1)的输出结果(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] ChannelPair 要被交换的通道数号,即n可为0,1,2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_InvertChannel(ETM_Type *pETM, uint8_t u8ChannelPair)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && u8ChannelPair <= 2);
|
||||
|
||||
pETM->INVCTRL |= 1<<u8ChannelPair;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_INVC_MASK)
|
||||
{
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWINVC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
else if(pETM->SYNCONF & ETM_SYNCONF_HWINVC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM模块初始化函数.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] pConfig 配置ETM模块的结构体.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_Init(ETM_Type *pETM, ETM_ConfigType *pConfig)
|
||||
{
|
||||
ASSERT((ETM0 == pETM) || (ETM1 == pETM) || (ETM2 == pETM));
|
||||
if(ETM0 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
}
|
||||
|
||||
/*关闭计数器*/
|
||||
pETM->SC = 0;
|
||||
pETM->MODE = pConfig->mode;
|
||||
pETM->MOD = pConfig->modulo;
|
||||
pETM->CNT = pConfig->cnt;
|
||||
|
||||
if( pETM->MODE & ETM_MODE_ETMEN_MASK )
|
||||
{
|
||||
/* 当 ETMEN = 1时, 下列寄存器可以写入 */
|
||||
pETM->COMBINE = pConfig->combine;
|
||||
pETM->CNTIN = pConfig->cntin;
|
||||
pETM->SYNC = pConfig->sync;
|
||||
pETM->OUTINIT = pConfig->outinit;
|
||||
pETM->OUTMASK = pConfig->outmask;
|
||||
pETM->DEADETME = pConfig->deadETMe;
|
||||
pETM->EXTTRIG = pConfig->exttrig;
|
||||
pETM->POL = pConfig->pol;
|
||||
pETM->FMS = pConfig->fms;
|
||||
pETM->FILTER = pConfig->filter;
|
||||
pETM->FLTCTRL = pConfig->fltctrl;
|
||||
pETM->FLTPOL = pConfig->fltpol;
|
||||
pETM->CONF = pConfig->conf;
|
||||
pETM->SYNCONF = pConfig->synconf;
|
||||
pETM->SWOCTRL = pConfig->swoctrl;
|
||||
pETM->PWMLOAD = pConfig->pwmload;
|
||||
}
|
||||
/* 写入状态控制寄存器来使能时钟*/
|
||||
pETM->SC = pConfig->sc;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位ETM模块.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_DeInit(ETM_Type *pETM)
|
||||
{
|
||||
ASSERT((ETM0 == pETM) || (ETM1 == pETM) || (ETM2 == pETM));
|
||||
pETM->SC = 0;
|
||||
pETM->MOD = 0;
|
||||
pETM->CNT = 0;
|
||||
if(ETM2 == pETM)
|
||||
{
|
||||
pETM->MODE = 0x4;
|
||||
pETM->COMBINE = 0;
|
||||
pETM->CNTIN = 0;
|
||||
pETM->SYNC = 0;
|
||||
pETM->OUTINIT = 0;
|
||||
pETM->OUTMASK = 0;
|
||||
pETM->DEADETME = 0;
|
||||
pETM->EXTTRIG = 0;
|
||||
pETM->POL = 0;
|
||||
pETM->FMS = 0;
|
||||
pETM->FILTER = 0;
|
||||
pETM->FLTCTRL = 0;
|
||||
pETM->FLTPOL = 0;
|
||||
pETM->CONF = 0;
|
||||
pETM->SYNCONF = 0;
|
||||
pETM->SWOCTRL = 0;
|
||||
pETM->PWMLOAD = 0;
|
||||
}
|
||||
/* 禁止ETM模块的时钟 */
|
||||
if (ETM0 == pETM)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ETM0_MASK;
|
||||
NVIC_DisableIRQ(ETM0_IRQn);
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ETM1_MASK;
|
||||
NVIC_DisableIRQ(ETM1_IRQn);
|
||||
}
|
||||
else if (ETM2 == pETM)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ETM2_MASK;
|
||||
NVIC_DisableIRQ(ETM2_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置ETM通道, 包括通道状态及控制寄存器CnSC和通道计数值寄存器CnV.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] ETM_Channel ETM的通道号.
|
||||
* @param[in] pTETMCH_Params 配置ETM通道参数的结构体.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_ChannelInit(ETM_Type *pETM, uint8_t u8ETM_Channel, ETM_ChParamsType *pTETMCH_Params)
|
||||
{
|
||||
ASSERT((ETM0 == pETM) || (ETM1 == pETM) || (ETM2 == pETM)); //断言检测通道的正确性
|
||||
|
||||
if (ETM0 == pETM)
|
||||
{
|
||||
ASSERT(u8ETM_Channel < 2);
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
ASSERT(u8ETM_Channel < 2);
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(u8ETM_Channel < 6);
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
}
|
||||
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = pTETMCH_Params->u8CnSC;
|
||||
pETM->CONTROLS[u8ETM_Channel].CnV = pTETMCH_Params->u16CnV;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置级联模式及占空比(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] ETM_Channel 奇通道数:1、3、5.
|
||||
* @param[in] dutyCycle 设置占空比,若DutyCycle为10,那么占空比就为10%.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SetDutyCycleCombine(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8DutyCycle)
|
||||
{
|
||||
uint16_t cnv = pETM->CONTROLS[u8ETM_Channel-1].CnV;
|
||||
uint16_t modulo = pETM->MOD;
|
||||
|
||||
ASSERT((1 == u8ETM_Channel) || (3 == u8ETM_Channel) || (5 == u8ETM_Channel));
|
||||
|
||||
cnv += (u8DutyCycle * (modulo+1)) / 100;
|
||||
if(cnv > modulo)
|
||||
{
|
||||
cnv = modulo - 1;
|
||||
}
|
||||
pETM->CONTROLS[u8ETM_Channel].CnV = cnv ;
|
||||
|
||||
pETM->PWMLOAD |= ETM_PWMLOAD_LDOK_MASK | (1<<u8ETM_Channel);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置寄存器 ETMx_SYNCONF部分位置位,其中里面包含了软件输出的控制是否由硬件触发HW或是否有软件出发SW(ETM2)
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u32ConfigValue 用来配置SYNCONF寄存器.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SyncConfigActivate(ETM_Type *pETM, uint32_t u32ConfigValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->SYNCONF |= u32ConfigValue;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置寄存器 ETMx_SYNCONF部分位清除,其中里面包含了软件输出的控制是否由硬件触发HW或是否有软件出发SW(ETM2)
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u32ConfigValue 用来配置SYNCONF寄存器.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SyncConfigDeactivate(ETM_Type *pETM, uint32_t u32ConfigValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->SYNCONF &= ~u32ConfigValue;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置回调函数入口.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] pfnCallback 回调函数地址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SetCallback(ETM_Type *pETM, ETM_CallbackPtr pfnCallback)
|
||||
{
|
||||
ETM_Callback[((uint32_t)pETM - (uint32_t)ETM0_BASE)>>12] = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM0通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM0_Isr(void)
|
||||
{
|
||||
if(ETM_Callback[0])
|
||||
{
|
||||
ETM_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM1通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM1_Isr(void)
|
||||
{
|
||||
if(ETM_Callback[1])
|
||||
{
|
||||
ETM_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM2_Isr(void)
|
||||
{
|
||||
if(ETM_Callback[2])
|
||||
{
|
||||
ETM_Callback[2]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,376 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file gpio.c
|
||||
* @brief 通用输入输出模块(GPIO)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
**************************************************************************/
|
||||
#include "gpio.h"
|
||||
|
||||
//GPIOA | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
|
||||
// Px | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | C7 | C6 | C5 | C4 | C3 | C2 | C1 | C0 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
|
||||
|
||||
//GPIOB | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
|
||||
// Px | H7 | H6 | -- | -- | -- | H2 | H1 | H0 | -- | -- | -- | -- | G3 | G2 | G1 | C0 | F7 | F6 | F5 | F4 | F3 | F2 | F1 | F0 | E7 | E6 | E5 | E4 | E3 | E2 | E1 | E0 |
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 复位GPIO模块.
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_DeInit(GPIO_Type *pGPIO)
|
||||
{
|
||||
/* Sanity check */
|
||||
#if defined(CPU_NV32)
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
#endif
|
||||
pGPIO->PCOR = 0x00000000; /* 端口清零输出寄存器 */
|
||||
pGPIO->PDDR = 0x00000000; /* 端口数据方向寄存器 */
|
||||
//pGPIO->PDIR = 0x00000000; /* 端口数据输入寄存器 */
|
||||
pGPIO->PDOR = 0x00000000; /* 端口数据输出寄存器 */
|
||||
pGPIO->PIDR = 0xFFFFFFFF; /* 端口输入禁用寄存器 */
|
||||
pGPIO->PSOR = 0x00000000; /* 端口置位输出寄存器 */
|
||||
pGPIO->PTOR = 0x00000000; /* 端口切换输出寄存器 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 初始化GPIO引脚属性
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码(GPIO_PTA0_MASK, GPIO_PTA1_MASK...)
|
||||
* @param[in] sGpioType 引脚属性(输入GPIO_PinInput、输出GPIO_PinOutput、输出高电流驱动GPIO_PinOutput_HighCurrent、输入并开启上拉GPIO_PinInput_InternalPullup)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ 注:
|
||||
* . 如果引脚配置为输入,禁用高电流驱动
|
||||
* . 如果引脚配置为输出,禁用内部上拉,内部上拉仅为输入模式使用
|
||||
* 仅PTH1/0, PTE1/0, PTD1/0, PTB5/4 支持高电流驱动.
|
||||
*****************************************************************************/
|
||||
void GPIO_Init(GPIO_Type *pGPIO, uint32_t u32PinMask, GPIO_PinConfigType sGpioType)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
/* 配置GPIO为输入或者输出 */
|
||||
if ((sGpioType == GPIO_PinOutput) || (sGpioType == GPIO_PinOutput_HighCurrent))
|
||||
{
|
||||
pGPIO->PDDR |= u32PinMask; /* 引脚配置为通用输出*/
|
||||
pGPIO->PIDR |= u32PinMask; /* 置位端口输入禁用寄存器*/
|
||||
}
|
||||
else if ((sGpioType == GPIO_PinInput) || (sGpioType == GPIO_PinInput_InternalPullup))
|
||||
{
|
||||
pGPIO->PDDR &= ~u32PinMask; /* 引脚配置为通用输入 */
|
||||
pGPIO->PIDR &= ~u32PinMask; /* 清零端口输入禁用寄存器 */
|
||||
}
|
||||
/* 设置GPIO端口输入上拉 */
|
||||
switch ((uint32_t)pGPIO)
|
||||
{
|
||||
case GPIOA_BASE:
|
||||
(sGpioType == GPIO_PinInput_InternalPullup) ? (PORT->PUEL |= u32PinMask) : (PORT->PUEL &= ~u32PinMask);
|
||||
break;
|
||||
case GPIOB_BASE:
|
||||
(sGpioType == GPIO_PinInput_InternalPullup) ? (PORT->PUEH |= u32PinMask) : (PORT->PUEH &= ~u32PinMask);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* 设置GPIO端口为高电流驱动输出 */
|
||||
if (pGPIO == GPIOA)
|
||||
{
|
||||
if (u32PinMask & GPIO_PTB4_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB4_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTB5_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB5_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTD0_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD0_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTD1_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD1_MASK;
|
||||
}
|
||||
}
|
||||
if (pGPIO == GPIOB)
|
||||
{
|
||||
if (u32PinMask & GPIO_PTE0_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE0_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTE1_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE1_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTH0_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH0_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTH1_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH1_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 切换GPIO端口数据输出
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码(GPIO_PTA0_MASK, GPIO_PTA1_MASK...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_Toggle(GPIO_Type *pGPIO, uint32_t u32PinMask)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
pGPIO->PTOR = u32PinMask; /* 32位引脚掩码确定要切换输出的引脚 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 读取端口输入数据寄存器
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
*
|
||||
* @return GPIOx->PDIR端口输入寄存器32位数值
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t GPIO_Read(GPIO_Type *pGPIO)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
return (pGPIO->PDIR); /* 读端口数据输入寄存器 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 读取某个引脚的电平
|
||||
*
|
||||
* @param[in] pGPIO 指向GPIO模块 GPIOA/GPIOB.
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return 端口数据寄存器某一位的值
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t GPIO_BitRead(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
ASSERT(GPIO_Pin < GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
if (((1 << GPIO_Pin) & GPIOA->PDIR) > 0) /*判断要读取的位,对应的数值是1还是0*/
|
||||
data = 0x1; /* 如果是1返回1,是0则返回0 */
|
||||
else
|
||||
data = 0x0;
|
||||
}
|
||||
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - 32);
|
||||
|
||||
if (((1 << GPIO_Pin) & GPIOB->PDIR) > 0) /*判断要读取的位,对应的数值是1还是0*/
|
||||
data = 0x1; /* 如果是1返回1,是0则返回0 */
|
||||
else
|
||||
data = 0x0;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 写数据到端口数据输出寄存器
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
* @param[in] u32Value 写入到端口数据输出寄存器GPIOx->PDOR的值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_Write(GPIO_Type *pGPIO, uint32_t u32Value)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
pGPIO->PDOR = u32Value; /* 写数据到端口数据输出寄存器 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 初始化GPIO引脚属性
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0、PIO_PTA1...)
|
||||
* @param[in] GPIO_PinConfig 引脚属性(输入GPIO_PinInput、输出GPIO_PinOutput、输出高电流驱动GPIO_PinOutput_HighCurrent、输入并开启上拉GPIO_PinInput_InternalPullup)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinInit(GPIO_PinType GPIO_Pin, GPIO_PinConfigType GPIO_PinConfig)
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT(GPIO_Pin < GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
switch (GPIO_PinConfig)
|
||||
{
|
||||
case GPIO_PinOutput:
|
||||
GPIOA->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOA->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一*/
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉 */
|
||||
break;
|
||||
case GPIO_PinInput:
|
||||
GPIOA->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOA->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
case GPIO_PinInput_InternalPullup:
|
||||
GPIOA->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOA->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEL |= (1 << GPIO_Pin); /* 使能内部上拉 */
|
||||
break;
|
||||
case GPIO_PinOutput_HighCurrent:
|
||||
GPIOA->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOA->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一 */
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - 32);
|
||||
switch (GPIO_PinConfig)
|
||||
{
|
||||
case GPIO_PinOutput:
|
||||
GPIOB->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOB->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一 */
|
||||
PORT->PUEH &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
case GPIO_PinInput:
|
||||
GPIOB->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOB->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEH &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
case GPIO_PinInput_InternalPullup:
|
||||
GPIOB->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOB->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEH |= (1 << GPIO_Pin); /* 使能内部上拉*/
|
||||
break;
|
||||
case GPIO_PinOutput_HighCurrent:
|
||||
GPIOA->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOA->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一 */
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 配置GPIO输出高电流驱动 */
|
||||
if (GPIO_PinConfig == GPIO_PinOutput_HighCurrent)
|
||||
{
|
||||
switch (GPIO_Pin)
|
||||
{
|
||||
case GPIO_PTB4:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB4_MASK;
|
||||
break;
|
||||
case GPIO_PTB5:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB5_MASK;
|
||||
break;
|
||||
case GPIO_PTD0:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD0_MASK;
|
||||
break;
|
||||
case GPIO_PTD1:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD1_MASK;
|
||||
break;
|
||||
case GPIO_PTE0:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE0_MASK;
|
||||
break;
|
||||
case GPIO_PTE1:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE1_MASK;
|
||||
break;
|
||||
case GPIO_PTH0:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH0_MASK;
|
||||
break;
|
||||
case GPIO_PTH1:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH1_MASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 切换GPIO端口数据切换输出
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinToggle(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
ASSERT(GPIO_Pin <= GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
GPIOA->PTOR = (1 << GPIO_Pin);
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - GPIO_PTE0);
|
||||
GPIOB->PTOR = (1 << GPIO_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief GPIO端口数据输出置1
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinSet(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
ASSERT(GPIO_Pin <= GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
GPIOA->PSOR = (1 << GPIO_Pin);
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - GPIO_PTE0);
|
||||
GPIOB->PSOR = (1 << GPIO_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief GPIO端口数据输出清零
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinClear(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
ASSERT(GPIO_Pin <= GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
GPIOA->PCOR = (1 << GPIO_Pin);
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - GPIO_PTE0);
|
||||
GPIOB->PCOR = (1 << GPIO_Pin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,583 @@
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "stdint.h"
|
||||
#include "core_cm0plus.h"
|
||||
#include "bos.h"
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define GPIO_ALIAS_OFF 0x000F0000L
|
||||
#define BOS_BIT_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t) (((uint32_t)&ADDR)-GPIO_ALIAS_OFF)) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPIO位带操作宏定义
|
||||
*
|
||||
******************************************************************************/
|
||||
#define PTA0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,0) //PTA0端口数据输出为高
|
||||
#define PTA0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,0) //PTA0端口数据输出为低
|
||||
#define PTA0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,0) //PTA0端口输出切换
|
||||
|
||||
#define PTA1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,1)
|
||||
|
||||
#define PTA2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,2)
|
||||
|
||||
#define PTA3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,3)
|
||||
|
||||
#define PTA4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,4)
|
||||
|
||||
#define PTA5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,5)
|
||||
|
||||
#define PTA6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,6)
|
||||
|
||||
#define PTA7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,7)
|
||||
|
||||
#define PTB0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,8) //PTB0端口数据输出为高
|
||||
#define PTB0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,8) //PTB0端口数据输出为低
|
||||
#define PTB0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,8) //PTB0端口数据输出切换
|
||||
|
||||
#define PTB1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,9)
|
||||
|
||||
#define PTB2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,10)
|
||||
|
||||
#define PTB3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,11)
|
||||
|
||||
#define PTB4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,12)
|
||||
|
||||
#define PTB5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,13)
|
||||
|
||||
#define PTB6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,14)
|
||||
|
||||
#define PTB7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,15)
|
||||
|
||||
#define PTC0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,16) //PTC0端口数据输出为高
|
||||
#define PTC0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,16) //PTC0端口数据输出为低
|
||||
#define PTC0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,16) //PTC0端口数据输出切换
|
||||
|
||||
#define PTC1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,17)
|
||||
|
||||
#define PTC2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,18)
|
||||
|
||||
#define PTC3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,19)
|
||||
|
||||
#define PTC4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,20)
|
||||
|
||||
#define PTC5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,21)
|
||||
|
||||
#define PTC6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,22)
|
||||
|
||||
#define PTC7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,23)
|
||||
|
||||
#define PTD0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,24) //PTD0端口数据输出为高
|
||||
#define PTD0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,24) //PTD0端口数据输出为低
|
||||
#define PTD0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,24) //PTD0端口数据输出切换
|
||||
|
||||
#define PTD1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,25)
|
||||
|
||||
#define PTD2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,26)
|
||||
|
||||
#define PTD3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,27)
|
||||
|
||||
#define PTD4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,28)
|
||||
|
||||
#define PTD5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,29)
|
||||
|
||||
#define PTD6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,30)
|
||||
|
||||
#define PTD7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,31)
|
||||
|
||||
#define PTE0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,0)
|
||||
|
||||
#define PTE1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,1) //PTE0端口数据输出为高
|
||||
#define PTE1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,1) //PTE0端口数据输出为低
|
||||
#define PTE1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,1) //PTE0端口数据输出切换
|
||||
|
||||
#define PTE2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,2)
|
||||
|
||||
#define PTE3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,3)
|
||||
|
||||
#define PTE4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,4)
|
||||
|
||||
#define PTE5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,5)
|
||||
|
||||
#define PTE6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,6)
|
||||
|
||||
#define PTE7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,7)
|
||||
|
||||
#define PTF0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,8) //PTF0端口数据输出为高
|
||||
#define PTF0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,8) //PTF0端口数据输出为低
|
||||
#define PTF0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,8) //PTF0端口数据输出切换
|
||||
|
||||
#define PTF1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,9)
|
||||
|
||||
#define PTF2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,10)
|
||||
|
||||
#define PTF3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,11)
|
||||
|
||||
#define PTF4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,12)
|
||||
|
||||
#define PTF5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,13)
|
||||
|
||||
#define PTF6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,14)
|
||||
|
||||
#define PTF7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,15)
|
||||
|
||||
#define PTG0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,16) //PTG0端口数据输出为高
|
||||
#define PTG0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,16) //PTG0端口数据输出为低
|
||||
#define PTG0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,16) //PTG0端口数据输出切换
|
||||
|
||||
#define PTG1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,17)
|
||||
|
||||
#define PTG2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,18)
|
||||
|
||||
#define PTG3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,19)
|
||||
|
||||
#define PTG4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,20)
|
||||
|
||||
#define PTG5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,21)
|
||||
|
||||
#define PTG6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,22)
|
||||
|
||||
#define PTG7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,23)
|
||||
|
||||
#define PTH0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,24) //PTH0端口数据输出为高
|
||||
#define PTH0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,24) //PTH0端口数据输出为低
|
||||
#define PTH0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,24) //PTH0端口数据输出切换
|
||||
|
||||
#define PTH1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,25)
|
||||
|
||||
#define PTH2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,26)
|
||||
|
||||
#define PTH3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,27)
|
||||
|
||||
#define PTH4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,28)
|
||||
|
||||
#define PTH5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,29)
|
||||
|
||||
#define PTH6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,30)
|
||||
|
||||
#define PTH7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,31)
|
||||
|
||||
#define PTA0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,0,1) //读取PA0端口输入数据
|
||||
#define PTA1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,1,1)
|
||||
#define PTA2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,2,1)
|
||||
#define PTA3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,3,1)
|
||||
#define PTA4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,4,1)
|
||||
#define PTA5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,5,1)
|
||||
#define PTA6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,6,1)
|
||||
#define PTA7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,7,1)
|
||||
|
||||
#define PTB0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,8,1) //读取PB0端口输入数据
|
||||
#define PTB1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,9,1)
|
||||
#define PTB2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,10,1)
|
||||
#define PTB3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,11,1)
|
||||
#define PTB4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,12,1)
|
||||
#define PTB5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,13,1)
|
||||
#define PTB6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,14,1)
|
||||
#define PTB7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,15,1)
|
||||
|
||||
#define PTC0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,16,1) //读取PC0端口输入数据
|
||||
#define PTC1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,17,1)
|
||||
#define PTC2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,18,1)
|
||||
#define PTC3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,19,1)
|
||||
#define PTC4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,20,1)
|
||||
#define PTC5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,21,1)
|
||||
#define PTC6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,22,1)
|
||||
#define PTC7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,23,1)
|
||||
|
||||
#define PTD0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,24,1) //读取PD0端口输入数据
|
||||
#define PTD1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,25,1)
|
||||
#define PTD2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,26,1)
|
||||
#define PTD3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,27,1)
|
||||
#define PTD4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,28,1)
|
||||
#define PTD5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,29,1)
|
||||
#define PTD6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,30,1)
|
||||
#define PTD7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,31,1)
|
||||
|
||||
#define PTE0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,0,1) //读取PE0端口输入数据
|
||||
#define PTE1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,1,1)
|
||||
#define PTE2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,2,1)
|
||||
#define PTE3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,3,1)
|
||||
#define PTE4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,4,1)
|
||||
#define PTE5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,5,1)
|
||||
#define PTE6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,6,1)
|
||||
#define PTE7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,7,1)
|
||||
|
||||
#define PTF0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,8,1) //读取PF0端口输入数据
|
||||
#define PTF1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,9,1)
|
||||
#define PTF2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,10,1)
|
||||
#define PTF3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,11,1)
|
||||
#define PTF4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,12,1)
|
||||
#define PTF5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,13,1)
|
||||
#define PTF6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,14,1)
|
||||
#define PTF7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,15,1)
|
||||
|
||||
#define PTG0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,16,1) //读取PG0端口输入数据 Modify
|
||||
#define PTG1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,17,1)
|
||||
#define PTG2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,18,1)
|
||||
#define PTG3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,19,1)
|
||||
#define PTG4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,20,1)
|
||||
#define PTG5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,21,1)
|
||||
#define PTG6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,22,1)
|
||||
#define PTG7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,23,1)
|
||||
|
||||
#define PTH0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,24,1) //读取PH0端口输入数据
|
||||
#define PTH1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,25,1)
|
||||
#define PTH2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,26,1)
|
||||
#define PTH3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,27,1)
|
||||
#define PTH4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,28,1)
|
||||
#define PTH5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,29,1)
|
||||
#define PTH6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,30,1)
|
||||
#define PTH7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,31,1)
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚名
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* 用于GPIO */
|
||||
GPIO_PTA0 = 0, /*!< GPIO Pin PTA0 */
|
||||
GPIO_PTA1, /*!< GPIO Pin PTA1 */
|
||||
GPIO_PTA2, /*!< GPIO Pin PTA2 */
|
||||
GPIO_PTA3, /*!< GPIO Pin PTA3 */
|
||||
GPIO_PTA4, /*!< GPIO Pin PTA4 */
|
||||
GPIO_PTA5, /*!< GPIO Pin PTA5 */
|
||||
GPIO_PTA6, /*!< GPIO Pin PTA6 */
|
||||
GPIO_PTA7, /*!< GPIO Pin PTA7 */
|
||||
GPIO_PTB0, /*!< GPIO Pin PTB0 */
|
||||
GPIO_PTB1, /*!< GPIO Pin PTB1 */
|
||||
GPIO_PTB2, /*!< GPIO Pin PTB2 */
|
||||
GPIO_PTB3, /*!< GPIO Pin PTB3 */
|
||||
GPIO_PTB4, /*!< GPIO Pin PTB4 */
|
||||
GPIO_PTB5, /*!< GPIO Pin PTB5 */
|
||||
GPIO_PTB6, /*!< GPIO Pin PTB6 */
|
||||
GPIO_PTB7, /*!< GPIO Pin PTB7 */
|
||||
GPIO_PTC0, /*!< GPIO Pin PTC0 */
|
||||
GPIO_PTC1, /*!< GPIO Pin PTC1 */
|
||||
GPIO_PTC2, /*!< GPIO Pin PTC2 */
|
||||
GPIO_PTC3, /*!< GPIO Pin PTC3 */
|
||||
GPIO_PTC4, /*!< GPIO Pin PTC4 */
|
||||
GPIO_PTC5, /*!< GPIO Pin PTC5 */
|
||||
GPIO_PTC6, /*!< GPIO Pin PTC6 */
|
||||
GPIO_PTC7, /*!< GPIO Pin PTC7 */
|
||||
GPIO_PTD0, /*!< GPIO Pin PTD0 */
|
||||
GPIO_PTD1, /*!< GPIO Pin PTD1 */
|
||||
GPIO_PTD2, /*!< GPIO Pin PTD2 */
|
||||
GPIO_PTD3, /*!< GPIO Pin PTD3 */
|
||||
GPIO_PTD4, /*!< GPIO Pin PTD4 */
|
||||
GPIO_PTD5, /*!< GPIO Pin PTD5 */
|
||||
GPIO_PTD6, /*!< GPIO Pin PTD6 */
|
||||
GPIO_PTD7, /*!< GPIO Pin PTD7 */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0, /*!< GPIO Pin PTE0 */
|
||||
GPIO_PTE1, /*!< GPIO Pin PTE1 */
|
||||
GPIO_PTE2, /*!< GPIO Pin PTE2 */
|
||||
GPIO_PTE3, /*!< GPIO Pin PTE3 */
|
||||
GPIO_PTE4, /*!< GPIO Pin PTE4 */
|
||||
GPIO_PTE5, /*!< GPIO Pin PTE5 */
|
||||
GPIO_PTE6, /*!< GPIO Pin PTE6 */
|
||||
GPIO_PTE7, /*!< GPIO Pin PTE7 */
|
||||
GPIO_PTF0, /*!< GPIO Pin PTF0 */
|
||||
GPIO_PTF1, /*!< GPIO Pin PTF1 */
|
||||
GPIO_PTF2, /*!< GPIO Pin PTF2 */
|
||||
GPIO_PTF3, /*!< GPIO Pin PTF3 */
|
||||
GPIO_PTF4, /*!< GPIO Pin PTF4 */
|
||||
GPIO_PTF5, /*!< GPIO Pin PTF5 */
|
||||
GPIO_PTF6, /*!< GPIO Pin PTF6 */
|
||||
GPIO_PTF7, /*!< GPIO Pin PTF7 */
|
||||
GPIO_PTG0, /*!< GPIO Pin PTG0 */
|
||||
GPIO_PTG1, /*!< GPIO Pin PTG1 */
|
||||
GPIO_PTG2, /*!< GPIO Pin PTG2 */
|
||||
GPIO_PTG3, /*!< GPIO Pin PTG3 */
|
||||
GPIO_PTG4, /*!< GPIO Pin PTG4 */
|
||||
GPIO_PTG5, /*!< GPIO Pin PTG5 */
|
||||
GPIO_PTG6, /*!< GPIO Pin PTG6 */
|
||||
GPIO_PTG7, /*!< GPIO Pin PTG7 */
|
||||
GPIO_PTH0, /*!< GPIO Pin PTH0 */
|
||||
GPIO_PTH1, /*!< GPIO Pin PTH1 */
|
||||
GPIO_PTH2, /*!< GPIO Pin PTH2 */
|
||||
GPIO_PTH3, /*!< GPIO Pin PTH3 */
|
||||
GPIO_PTH4, /*!< GPIO Pin PTH4 */
|
||||
GPIO_PTH5, /*!< GPIO Pin PTH5 */
|
||||
GPIO_PTH6, /*!< GPIO Pin PTH6 */
|
||||
GPIO_PTH7, /*!< GPIO Pin PTH7 */
|
||||
GPIO_PIN_MAX,
|
||||
} GPIO_PinType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚掩码
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* in GPIOA register */
|
||||
GPIO_PTA0_MASK = (1<<0), /*!< GPIO Pin PTA0 bit mask */
|
||||
GPIO_PTA1_MASK = (1<<1), /*!< GPIO Pin PTA1 bit mask */
|
||||
GPIO_PTA2_MASK = (1<<2), /*!< GPIO Pin PTA2 bit mask */
|
||||
GPIO_PTA3_MASK = (1<<3), /*!< GPIO Pin PTA3 bit mask */
|
||||
GPIO_PTA4_MASK = (1<<4), /*!< GPIO Pin PTA4 bit mask */
|
||||
GPIO_PTA5_MASK = (1<<5), /*!< GPIO Pin PTA5 bit mask */
|
||||
GPIO_PTA6_MASK = (1<<6), /*!< GPIO Pin PTA6 bit mask */
|
||||
GPIO_PTA7_MASK = (1<<7), /*!< GPIO Pin PTA7 bit mask */
|
||||
GPIO_PTB0_MASK = (1<<8), /*!< GPIO Pin PTB0 bit mask */
|
||||
GPIO_PTB1_MASK = (1<<9), /*!< GPIO Pin PTB1 bit mask */
|
||||
GPIO_PTB2_MASK = (1<<10), /*!< GPIO Pin PTB2 bit mask */
|
||||
GPIO_PTB3_MASK = (1<<11), /*!< GPIO Pin PTB3 bit mask */
|
||||
GPIO_PTB4_MASK = (1<<12), /*!< GPIO Pin PTB4 bit mask */
|
||||
GPIO_PTB5_MASK = (1<<13), /*!< GPIO Pin PTB5 bit mask */
|
||||
GPIO_PTB6_MASK = (1<<14), /*!< GPIO Pin PTB6 bit mask */
|
||||
GPIO_PTB7_MASK = (1<<15), /*!< GPIO Pin PTB7 bit mask */
|
||||
GPIO_PTC0_MASK = (1<<16), /*!< GPIO Pin PTC0 bit mask */
|
||||
GPIO_PTC1_MASK = (1<<17), /*!< GPIO Pin PTC1 bit mask */
|
||||
GPIO_PTC2_MASK = (1<<18), /*!< GPIO Pin PTC2 bit mask */
|
||||
GPIO_PTC3_MASK = (1<<19), /*!< GPIO Pin PTC3 bit mask */
|
||||
GPIO_PTC4_MASK = (1<<20), /*!< GPIO Pin PTC4 bit mask */
|
||||
GPIO_PTC5_MASK = (1<<21), /*!< GPIO Pin PTC5 bit mask */
|
||||
GPIO_PTC6_MASK = (1<<22), /*!< GPIO Pin PTC6 bit mask */
|
||||
GPIO_PTC7_MASK = (1<<23), /*!< GPIO Pin PTC7 bit mask */
|
||||
GPIO_PTD0_MASK = (1<<24), /*!< GPIO Pin PTD0 bit mask */
|
||||
GPIO_PTD1_MASK = (1<<25), /*!< GPIO Pin PTD1 bit mask */
|
||||
GPIO_PTD2_MASK = (1<<26), /*!< GPIO Pin PTD2 bit mask */
|
||||
GPIO_PTD3_MASK = (1<<27), /*!< GPIO Pin PTD3 bit mask */
|
||||
GPIO_PTD4_MASK = (1<<28), /*!< GPIO Pin PTD4 bit mask */
|
||||
GPIO_PTD5_MASK = (1<<29), /*!< GPIO Pin PTD5 bit mask */
|
||||
GPIO_PTD6_MASK = (1<<30), /*!< GPIO Pin PTD6 bit mask */
|
||||
GPIO_PTD7_MASK = (int)(0x80000000), /*!< GPIO Pin PTD7 bit mask */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0_MASK = (1<<0), /*!< GPIO Pin PTE0 bit mask */
|
||||
GPIO_PTE1_MASK = (1<<1), /*!< GPIO Pin PTE1 bit mask */
|
||||
GPIO_PTE2_MASK = (1<<2), /*!< GPIO Pin PTE2 bit mask */
|
||||
GPIO_PTE3_MASK = (1<<3), /*!< GPIO Pin PTE3 bit mask */
|
||||
GPIO_PTE4_MASK = (1<<4), /*!< GPIO Pin PTE4 bit mask */
|
||||
GPIO_PTE5_MASK = (1<<5), /*!< GPIO Pin PTE5 bit mask */
|
||||
GPIO_PTE6_MASK = (1<<6), /*!< GPIO Pin PTE6 bit mask */
|
||||
GPIO_PTE7_MASK = (1<<7), /*!< GPIO Pin PTE7 bit mask */
|
||||
GPIO_PTF0_MASK = (1<<8), /*!< GPIO Pin PTF0 bit mask */
|
||||
GPIO_PTF1_MASK = (1<<9), /*!< GPIO Pin PTF1 bit mask */
|
||||
GPIO_PTF2_MASK = (1<<10), /*!< GPIO Pin PTF2 bit mask */
|
||||
GPIO_PTF3_MASK = (1<<11), /*!< GPIO Pin PTF3 bit mask */
|
||||
GPIO_PTF4_MASK = (1<<12), /*!< GPIO Pin PTF4 bit mask */
|
||||
GPIO_PTF5_MASK = (1<<13), /*!< GPIO Pin PTF5 bit mask */
|
||||
GPIO_PTF6_MASK = (1<<14), /*!< GPIO Pin PTF6 bit mask */
|
||||
GPIO_PTF7_MASK = (1<<15), /*!< GPIO Pin PTF7 bit mask */
|
||||
GPIO_PTG0_MASK = (1<<16), /*!< GPIO Pin PTG0 bit mask */
|
||||
GPIO_PTG1_MASK = (1<<17), /*!< GPIO Pin PTG1 bit mask */
|
||||
GPIO_PTG2_MASK = (1<<18), /*!< GPIO Pin PTG2 bit mask */
|
||||
GPIO_PTG3_MASK = (1<<19), /*!< GPIO Pin PTG3 bit mask */
|
||||
GPIO_PTG4_MASK = (1<<20), /*!< GPIO Pin PTG4 bit mask */
|
||||
GPIO_PTG5_MASK = (1<<21), /*!< GPIO Pin PTG5 bit mask */
|
||||
GPIO_PTG6_MASK = (1<<22), /*!< GPIO Pin PTG6 bit mask */
|
||||
GPIO_PTG7_MASK = (1<<23), /*!< GPIO Pin PTG7 bit mask */
|
||||
GPIO_PTH0_MASK = (1<<24), /*!< GPIO Pin PTH0 bit mask */
|
||||
GPIO_PTH1_MASK = (1<<25), /*!< GPIO Pin PTH1 bit mask */
|
||||
GPIO_PTH2_MASK = (1<<26), /*!< GPIO Pin PTH2 bit mask */
|
||||
GPIO_PTH3_MASK = (1<<27), /*!< GPIO Pin PTH3 bit mask */
|
||||
GPIO_PTH4_MASK = (1<<28), /*!< GPIO Pin PTH4 bit mask */
|
||||
GPIO_PTH5_MASK = (1<<29), /*!< GPIO Pin PTH5 bit mask */
|
||||
GPIO_PTH6_MASK = (1<<30), /*!< GPIO Pin PTH6 bit mask */
|
||||
GPIO_PTH7_MASK = (int)(0x80000000), /*!< GPIO Pin PTH7 bit mask */
|
||||
} GPIO_PinMaskType;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义GPIO引脚配置类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*
|
||||
* . 如果引脚配置为输入,禁用高电流驱动
|
||||
* . 如果引脚配置为输出,禁用内部上拉
|
||||
* 仅PTH1/0, PTE1/0, PTD1/0, PTB5/4 支持高电流驱动.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GPIO_PinOutput = 0, /*!< 设置引脚为输出 */
|
||||
GPIO_PinInput, /*!< 设置引脚为输出*/
|
||||
GPIO_PinInput_InternalPullup, /*!< 设置引脚为输入且内部上拉 */
|
||||
GPIO_PinOutput_HighCurrent, /*!< 设置引脚为输出,高电流驱动*/
|
||||
} GPIO_PinConfigType;
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 切换FGPIO端口数据输出
|
||||
*
|
||||
* @param[in] pGPIO FGPIOA/FGPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码 ( GPIO_PTA0_MASK, GPIO_PTA1_MASK...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Toggle(FGPIO_Type *pFGPIO, uint32_t u32PinMask)
|
||||
{
|
||||
pFGPIO->PTOR = u32PinMask; /* 切换GPIO端口数据输出 */
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 读取FGPIO端口数据输入寄存器
|
||||
*
|
||||
* @param[in] pGPIO FGPIOA/FGPIOB.
|
||||
*
|
||||
* @return FGPIO端口数据输入寄存器32值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint32_t FGPIO_Read(FGPIO_Type *pFGPIO)
|
||||
{
|
||||
return (pFGPIO->PDIR); /*读端口数据输入寄存器*/
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 写数据到FGPIO端口数据输出寄存
|
||||
*
|
||||
* @param[in] pGPIO FGPIOA/FGPIOB.
|
||||
* @param[in] u32Value 写入的数值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Write(FGPIO_Type *pFGPIO, uint32_t u32Value)
|
||||
{
|
||||
pFGPIO->PDOR = u32Value; /*写数据到端口数据输出寄存器*/
|
||||
}
|
||||
|
||||
void GPIO_DeInit(GPIO_Type *pGPIO);
|
||||
void GPIO_Init(GPIO_Type *pGPIO, uint32_t u32PinMask, GPIO_PinConfigType sGpioType);
|
||||
void GPIO_Toggle(GPIO_Type *pGPIO, uint32_t u32PinMask);
|
||||
void GPIO_Write(GPIO_Type *pGPIO, uint32_t u32Value);
|
||||
void GPIO_PinInit(GPIO_PinType GPIO_Pin, GPIO_PinConfigType GPIO_PinConfig);
|
||||
void GPIO_PinToggle(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinSet(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinClear(GPIO_PinType GPIO_Pin);
|
||||
uint32_t GPIO_Read(GPIO_Type *pGPIO);
|
||||
uint8_t GPIO_BitRead(GPIO_PinType GPIO_Pin);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,601 @@
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "stdint.h"
|
||||
#include "core_cm0plus.h"
|
||||
#include "bos.h"
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define GPIO_ALIAS_OFF 0x000F0000L
|
||||
#define BOS_BIT_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t) (((uint32_t)&ADDR)-GPIO_ALIAS_OFF)) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPIO位带操作宏定义
|
||||
*
|
||||
******************************************************************************/
|
||||
#define PTA0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,0) //PTA0端口数据输出为高
|
||||
#define PTA0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,0) //PTA0端口数据输出为低
|
||||
#define PTA0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,0) //PTA0端口输出切换
|
||||
|
||||
#define PTA1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,1)
|
||||
|
||||
#define PTA2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,2)
|
||||
|
||||
#define PTA3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,3)
|
||||
|
||||
#define PTA4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,4)
|
||||
|
||||
#define PTA5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,5)
|
||||
|
||||
#define PTA6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,6)
|
||||
|
||||
#define PTA7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,7)
|
||||
|
||||
#define PTB0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,8) //PTB0端口数据输出为高
|
||||
#define PTB0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,8) //PTB0端口数据输出为低
|
||||
#define PTB0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,8) //PTB0端口数据输出切换
|
||||
|
||||
#define PTB1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,9)
|
||||
|
||||
#define PTB2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,10)
|
||||
|
||||
#define PTB3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,11)
|
||||
|
||||
#define PTB4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,12)
|
||||
|
||||
#define PTB5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,13)
|
||||
|
||||
#define PTB6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,14)
|
||||
|
||||
#define PTB7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,15)
|
||||
|
||||
#define PTC0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,16) //PTC0端口数据输出为高
|
||||
#define PTC0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,16) //PTC0端口数据输出为低
|
||||
#define PTC0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,16) //PTC0端口数据输出切换
|
||||
|
||||
#define PTC1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,17)
|
||||
|
||||
#define PTC2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,18)
|
||||
|
||||
#define PTC3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,19)
|
||||
|
||||
#define PTC4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,20)
|
||||
|
||||
#define PTC5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,21)
|
||||
|
||||
#define PTC6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,22)
|
||||
|
||||
#define PTC7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,23)
|
||||
|
||||
#define PTD0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,24) //PTD0端口数据输出为高
|
||||
#define PTD0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,24) //PTD0端口数据输出为低
|
||||
#define PTD0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,24) //PTD0端口数据输出切换
|
||||
|
||||
#define PTD1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,25)
|
||||
|
||||
#define PTD2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,26)
|
||||
|
||||
#define PTD3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,27)
|
||||
|
||||
#define PTD4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,28)
|
||||
|
||||
#define PTD5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,29)
|
||||
|
||||
#define PTD6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,30)
|
||||
|
||||
#define PTD7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,31)
|
||||
|
||||
#define PTE0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,0)
|
||||
|
||||
#define PTE1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,1) //PTE0端口数据输出为高
|
||||
#define PTE1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,1) //PTE0端口数据输出为低
|
||||
#define PTE1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,1) //PTE0端口数据输出切换
|
||||
|
||||
#define PTE2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,2)
|
||||
|
||||
#define PTE3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,3)
|
||||
|
||||
#define PTE4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,4)
|
||||
|
||||
#define PTE5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,5)
|
||||
|
||||
#define PTE6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,6)
|
||||
|
||||
#define PTE7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,7)
|
||||
|
||||
#define PTF0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,8) //PTF0端口数据输出为高
|
||||
#define PTF0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,8) //PTF0端口数据输出为低
|
||||
#define PTF0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,8) //PTF0端口数据输出切换
|
||||
|
||||
#define PTF1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,9)
|
||||
|
||||
#define PTF2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,10)
|
||||
|
||||
#define PTF3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,11)
|
||||
|
||||
#define PTF4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,12)
|
||||
|
||||
#define PTF5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,13)
|
||||
|
||||
#define PTF6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,14)
|
||||
|
||||
#define PTF7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,15)
|
||||
|
||||
#define PTG0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,16) //PTG0端口数据输出为高
|
||||
#define PTG0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,16) //PTG0端口数据输出为低
|
||||
#define PTG0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,16) //PTG0端口数据输出切换
|
||||
|
||||
#define PTG1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,17)
|
||||
|
||||
#define PTG2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,18)
|
||||
|
||||
#define PTG3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,19)
|
||||
|
||||
#define PTG4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,20)
|
||||
|
||||
#define PTG5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,21)
|
||||
|
||||
#define PTG6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,22)
|
||||
|
||||
#define PTG7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,23)
|
||||
|
||||
#define PTH0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,24) //PTH0端口数据输出为高
|
||||
#define PTH0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,24) //PTH0端口数据输出为低
|
||||
#define PTH0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,24) //PTH0端口数据输出切换
|
||||
|
||||
#define PTH1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,25)
|
||||
|
||||
#define PTH2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,26)
|
||||
|
||||
#define PTH3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,27)
|
||||
|
||||
#define PTH4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,28)
|
||||
|
||||
#define PTH5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,29)
|
||||
|
||||
#define PTH6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,30)
|
||||
|
||||
#define PTH7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,31)
|
||||
|
||||
#define PTA0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,0,1) //读取PA0端口输入数据
|
||||
#define PTA1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,1,1)
|
||||
#define PTA2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,2,1)
|
||||
#define PTA3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,3,1)
|
||||
#define PTA4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,4,1)
|
||||
#define PTA5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,5,1)
|
||||
#define PTA6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,6,1)
|
||||
#define PTA7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,7,1)
|
||||
|
||||
#define PTB0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,8,1) //读取PB0端口输入数据
|
||||
#define PTB1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,9,1)
|
||||
#define PTB2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,10,1)
|
||||
#define PTB3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,11,1)
|
||||
#define PTB4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,12,1)
|
||||
#define PTB5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,13,1)
|
||||
#define PTB6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,14,1)
|
||||
#define PTB7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,15,1)
|
||||
|
||||
#define PTC0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,16,1) //读取PC0端口输入数据
|
||||
#define PTC1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,17,1)
|
||||
#define PTC2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,18,1)
|
||||
#define PTC3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,19,1)
|
||||
#define PTC4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,20,1)
|
||||
#define PTC5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,21,1)
|
||||
#define PTC6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,22,1)
|
||||
#define PTC7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,23,1)
|
||||
|
||||
#define PTD0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,24,1) //读取PD0端口输入数据
|
||||
#define PTD1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,25,1)
|
||||
#define PTD2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,26,1)
|
||||
#define PTD3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,27,1)
|
||||
#define PTD4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,28,1)
|
||||
#define PTD5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,29,1)
|
||||
#define PTD6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,30,1)
|
||||
#define PTD7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,31,1)
|
||||
|
||||
#define PTE0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,0,1) //读取PE0端口输入数据
|
||||
#define PTE1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,1,1)
|
||||
#define PTE2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,2,1)
|
||||
#define PTE3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,3,1)
|
||||
#define PTE4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,4,1)
|
||||
#define PTE5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,5,1)
|
||||
#define PTE6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,6,1)
|
||||
#define PTE7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,7,1)
|
||||
|
||||
#define PTF0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,8,1) //读取PF0端口输入数据
|
||||
#define PTF1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,9,1)
|
||||
#define PTF2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,10,1)
|
||||
#define PTF3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,11,1)
|
||||
#define PTF4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,12,1)
|
||||
#define PTF5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,13,1)
|
||||
#define PTF6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,14,1)
|
||||
#define PTF7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,15,1)
|
||||
|
||||
#define PTG0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,16,1) //读取PG0端口输入数据 Modify
|
||||
#define PTG1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,17,1)
|
||||
#define PTG2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,18,1)
|
||||
#define PTG3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,19,1)
|
||||
#define PTG4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,20,1)
|
||||
#define PTG5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,21,1)
|
||||
#define PTG6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,22,1)
|
||||
#define PTG7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,23,1)
|
||||
|
||||
#define PTH0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,24,1) //读取PH0端口输入数据
|
||||
#define PTH1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,25,1)
|
||||
#define PTH2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,26,1)
|
||||
#define PTH3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,27,1)
|
||||
#define PTH4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,28,1)
|
||||
#define PTH5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,29,1)
|
||||
#define PTH6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,30,1)
|
||||
#define PTH7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,31,1)
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚名
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* 用于GPIO */
|
||||
GPIO_PTA0 = 0, /*!< GPIO Pin PTA0 */
|
||||
GPIO_PTA1, /*!< GPIO Pin PTA1 */
|
||||
GPIO_PTA2, /*!< GPIO Pin PTA2 */
|
||||
GPIO_PTA3, /*!< GPIO Pin PTA3 */
|
||||
GPIO_PTA4, /*!< GPIO Pin PTA4 */
|
||||
GPIO_PTA5, /*!< GPIO Pin PTA5 */
|
||||
GPIO_PTA6, /*!< GPIO Pin PTA6 */
|
||||
GPIO_PTA7, /*!< GPIO Pin PTA7 */
|
||||
GPIO_PTB0, /*!< GPIO Pin PTB0 */
|
||||
GPIO_PTB1, /*!< GPIO Pin PTB1 */
|
||||
GPIO_PTB2, /*!< GPIO Pin PTB2 */
|
||||
GPIO_PTB3, /*!< GPIO Pin PTB3 */
|
||||
GPIO_PTB4, /*!< GPIO Pin PTB4 */
|
||||
GPIO_PTB5, /*!< GPIO Pin PTB5 */
|
||||
GPIO_PTB6, /*!< GPIO Pin PTB6 */
|
||||
GPIO_PTB7, /*!< GPIO Pin PTB7 */
|
||||
GPIO_PTC0, /*!< GPIO Pin PTC0 */
|
||||
GPIO_PTC1, /*!< GPIO Pin PTC1 */
|
||||
GPIO_PTC2, /*!< GPIO Pin PTC2 */
|
||||
GPIO_PTC3, /*!< GPIO Pin PTC3 */
|
||||
GPIO_PTC4, /*!< GPIO Pin PTC4 */
|
||||
GPIO_PTC5, /*!< GPIO Pin PTC5 */
|
||||
GPIO_PTC6, /*!< GPIO Pin PTC6 */
|
||||
GPIO_PTC7, /*!< GPIO Pin PTC7 */
|
||||
GPIO_PTD0, /*!< GPIO Pin PTD0 */
|
||||
GPIO_PTD1, /*!< GPIO Pin PTD1 */
|
||||
GPIO_PTD2, /*!< GPIO Pin PTD2 */
|
||||
GPIO_PTD3, /*!< GPIO Pin PTD3 */
|
||||
GPIO_PTD4, /*!< GPIO Pin PTD4 */
|
||||
GPIO_PTD5, /*!< GPIO Pin PTD5 */
|
||||
GPIO_PTD6, /*!< GPIO Pin PTD6 */
|
||||
GPIO_PTD7, /*!< GPIO Pin PTD7 */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0, /*!< GPIO Pin PTE0 */
|
||||
GPIO_PTE1, /*!< GPIO Pin PTE1 */
|
||||
GPIO_PTE2, /*!< GPIO Pin PTE2 */
|
||||
GPIO_PTE3, /*!< GPIO Pin PTE3 */
|
||||
GPIO_PTE4, /*!< GPIO Pin PTE4 */
|
||||
GPIO_PTE5, /*!< GPIO Pin PTE5 */
|
||||
GPIO_PTE6, /*!< GPIO Pin PTE6 */
|
||||
GPIO_PTE7, /*!< GPIO Pin PTE7 */
|
||||
GPIO_PTF0, /*!< GPIO Pin PTF0 */
|
||||
GPIO_PTF1, /*!< GPIO Pin PTF1 */
|
||||
GPIO_PTF2, /*!< GPIO Pin PTF2 */
|
||||
GPIO_PTF3, /*!< GPIO Pin PTF3 */
|
||||
GPIO_PTF4, /*!< GPIO Pin PTF4 */
|
||||
GPIO_PTF5, /*!< GPIO Pin PTF5 */
|
||||
GPIO_PTF6, /*!< GPIO Pin PTF6 */
|
||||
GPIO_PTF7, /*!< GPIO Pin PTF7 */
|
||||
GPIO_PTG0, /*!< GPIO Pin PTG0 */
|
||||
GPIO_PTG1, /*!< GPIO Pin PTG1 */
|
||||
GPIO_PTG2, /*!< GPIO Pin PTG2 */
|
||||
GPIO_PTG3, /*!< GPIO Pin PTG3 */
|
||||
GPIO_PTG4, /*!< GPIO Pin PTG4 */
|
||||
GPIO_PTG5, /*!< GPIO Pin PTG5 */
|
||||
GPIO_PTG6, /*!< GPIO Pin PTG6 */
|
||||
GPIO_PTG7, /*!< GPIO Pin PTG7 */
|
||||
GPIO_PTH0, /*!< GPIO Pin PTH0 */
|
||||
GPIO_PTH1, /*!< GPIO Pin PTH1 */
|
||||
GPIO_PTH2, /*!< GPIO Pin PTH2 */
|
||||
GPIO_PTH3, /*!< GPIO Pin PTH3 */
|
||||
GPIO_PTH4, /*!< GPIO Pin PTH4 */
|
||||
GPIO_PTH5, /*!< GPIO Pin PTH5 */
|
||||
GPIO_PTH6, /*!< GPIO Pin PTH6 */
|
||||
GPIO_PTH7, /*!< GPIO Pin PTH7 */
|
||||
/* the following pins are not in NV322 */
|
||||
GPIO_PTI0, /*!< GPIO Pin PTI0 */
|
||||
GPIO_PTI1, /*!< GPIO Pin PTI1 */
|
||||
GPIO_PTI2, /*!< GPIO Pin PTI2 */
|
||||
GPIO_PTI3, /*!< GPIO Pin PTI3 */
|
||||
GPIO_PTI4, /*!< GPIO Pin PTI4 */
|
||||
GPIO_PTI5, /*!< GPIO Pin PTI5 */
|
||||
GPIO_PTI6, /*!< GPIO Pin PTI6 */
|
||||
GPIO_PTI7, /*!< GPIO Pin PTI7 */
|
||||
GPIO_PIN_MAX,
|
||||
} GPIO_PinType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚掩码
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* in GPIOA register */
|
||||
GPIO_PTA0_MASK = (1<<0), /*!< GPIO Pin PTA0 bit mask */
|
||||
GPIO_PTA1_MASK = (1<<1), /*!< GPIO Pin PTA1 bit mask */
|
||||
GPIO_PTA2_MASK = (1<<2), /*!< GPIO Pin PTA2 bit mask */
|
||||
GPIO_PTA3_MASK = (1<<3), /*!< GPIO Pin PTA3 bit mask */
|
||||
GPIO_PTA4_MASK = (1<<4), /*!< GPIO Pin PTA4 bit mask */
|
||||
GPIO_PTA5_MASK = (1<<5), /*!< GPIO Pin PTA5 bit mask */
|
||||
GPIO_PTA6_MASK = (1<<6), /*!< GPIO Pin PTA6 bit mask */
|
||||
GPIO_PTA7_MASK = (1<<7), /*!< GPIO Pin PTA7 bit mask */
|
||||
GPIO_PTB0_MASK = (1<<8), /*!< GPIO Pin PTB0 bit mask */
|
||||
GPIO_PTB1_MASK = (1<<9), /*!< GPIO Pin PTB1 bit mask */
|
||||
GPIO_PTB2_MASK = (1<<10), /*!< GPIO Pin PTB2 bit mask */
|
||||
GPIO_PTB3_MASK = (1<<11), /*!< GPIO Pin PTB3 bit mask */
|
||||
GPIO_PTB4_MASK = (1<<12), /*!< GPIO Pin PTB4 bit mask */
|
||||
GPIO_PTB5_MASK = (1<<13), /*!< GPIO Pin PTB5 bit mask */
|
||||
GPIO_PTB6_MASK = (1<<14), /*!< GPIO Pin PTB6 bit mask */
|
||||
GPIO_PTB7_MASK = (1<<15), /*!< GPIO Pin PTB7 bit mask */
|
||||
GPIO_PTC0_MASK = (1<<16), /*!< GPIO Pin PTC0 bit mask */
|
||||
GPIO_PTC1_MASK = (1<<17), /*!< GPIO Pin PTC1 bit mask */
|
||||
GPIO_PTC2_MASK = (1<<18), /*!< GPIO Pin PTC2 bit mask */
|
||||
GPIO_PTC3_MASK = (1<<19), /*!< GPIO Pin PTC3 bit mask */
|
||||
GPIO_PTC4_MASK = (1<<20), /*!< GPIO Pin PTC4 bit mask */
|
||||
GPIO_PTC5_MASK = (1<<21), /*!< GPIO Pin PTC5 bit mask */
|
||||
GPIO_PTC6_MASK = (1<<22), /*!< GPIO Pin PTC6 bit mask */
|
||||
GPIO_PTC7_MASK = (1<<23), /*!< GPIO Pin PTC7 bit mask */
|
||||
GPIO_PTD0_MASK = (1<<24), /*!< GPIO Pin PTD0 bit mask */
|
||||
GPIO_PTD1_MASK = (1<<25), /*!< GPIO Pin PTD1 bit mask */
|
||||
GPIO_PTD2_MASK = (1<<26), /*!< GPIO Pin PTD2 bit mask */
|
||||
GPIO_PTD3_MASK = (1<<27), /*!< GPIO Pin PTD3 bit mask */
|
||||
GPIO_PTD4_MASK = (1<<28), /*!< GPIO Pin PTD4 bit mask */
|
||||
GPIO_PTD5_MASK = (1<<29), /*!< GPIO Pin PTD5 bit mask */
|
||||
GPIO_PTD6_MASK = (1<<30), /*!< GPIO Pin PTD6 bit mask */
|
||||
GPIO_PTD7_MASK = (int)(0x80000000), /*!< GPIO Pin PTD7 bit mask ** thanks to @homeyou */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0_MASK = (1<<0), /*!< GPIO Pin PTE0 bit mask */
|
||||
GPIO_PTE1_MASK = (1<<1), /*!< GPIO Pin PTE1 bit mask */
|
||||
GPIO_PTE2_MASK = (1<<2), /*!< GPIO Pin PTE2 bit mask */
|
||||
GPIO_PTE3_MASK = (1<<3), /*!< GPIO Pin PTE3 bit mask */
|
||||
GPIO_PTE4_MASK = (1<<4), /*!< GPIO Pin PTE4 bit mask */
|
||||
GPIO_PTE5_MASK = (1<<5), /*!< GPIO Pin PTE5 bit mask */
|
||||
GPIO_PTE6_MASK = (1<<6), /*!< GPIO Pin PTE6 bit mask */
|
||||
GPIO_PTE7_MASK = (1<<7), /*!< GPIO Pin PTE7 bit mask */
|
||||
GPIO_PTF0_MASK = (1<<8), /*!< GPIO Pin PTF0 bit mask */
|
||||
GPIO_PTF1_MASK = (1<<9), /*!< GPIO Pin PTF1 bit mask */
|
||||
GPIO_PTF2_MASK = (1<<10), /*!< GPIO Pin PTF2 bit mask */
|
||||
GPIO_PTF3_MASK = (1<<11), /*!< GPIO Pin PTF3 bit mask */
|
||||
GPIO_PTF4_MASK = (1<<12), /*!< GPIO Pin PTF4 bit mask */
|
||||
GPIO_PTF5_MASK = (1<<13), /*!< GPIO Pin PTF5 bit mask */
|
||||
GPIO_PTF6_MASK = (1<<14), /*!< GPIO Pin PTF6 bit mask */
|
||||
GPIO_PTF7_MASK = (1<<15), /*!< GPIO Pin PTF7 bit mask */
|
||||
GPIO_PTG0_MASK = (1<<16), /*!< GPIO Pin PTG0 bit mask */
|
||||
GPIO_PTG1_MASK = (1<<17), /*!< GPIO Pin PTG1 bit mask */
|
||||
GPIO_PTG2_MASK = (1<<18), /*!< GPIO Pin PTG2 bit mask */
|
||||
GPIO_PTG3_MASK = (1<<19), /*!< GPIO Pin PTG3 bit mask */
|
||||
GPIO_PTG4_MASK = (1<<20), /*!< GPIO Pin PTG4 bit mask */
|
||||
GPIO_PTG5_MASK = (1<<21), /*!< GPIO Pin PTG5 bit mask */
|
||||
GPIO_PTG6_MASK = (1<<22), /*!< GPIO Pin PTG6 bit mask */
|
||||
GPIO_PTG7_MASK = (1<<23), /*!< GPIO Pin PTG7 bit mask */
|
||||
GPIO_PTH0_MASK = (1<<24), /*!< GPIO Pin PTH0 bit mask */
|
||||
GPIO_PTH1_MASK = (1<<25), /*!< GPIO Pin PTH1 bit mask */
|
||||
GPIO_PTH2_MASK = (1<<26), /*!< GPIO Pin PTH2 bit mask */
|
||||
GPIO_PTH3_MASK = (1<<27), /*!< GPIO Pin PTH3 bit mask */
|
||||
GPIO_PTH4_MASK = (1<<28), /*!< GPIO Pin PTH4 bit mask */
|
||||
GPIO_PTH5_MASK = (1<<29), /*!< GPIO Pin PTH5 bit mask */
|
||||
GPIO_PTH6_MASK = (1<<30), /*!< GPIO Pin PTH6 bit mask */
|
||||
GPIO_PTH7_MASK = (int)(0x80000000), /*!< GPIO Pin PTH7 bit mask ** thanks to @homeyou */
|
||||
/* in GPIOC register */
|
||||
GPIO_PTI0_MASK = (1<<0), /*!< GPIO Pin PTI0 bit mask */
|
||||
GPIO_PTI1_MASK = (1<<1), /*!< GPIO Pin PTI1 bit mask */
|
||||
GPIO_PTI2_MASK = (1<<2), /*!< GPIO Pin PTI2 bit mask */
|
||||
GPIO_PTI3_MASK = (1<<3), /*!< GPIO Pin PTI3 bit mask */
|
||||
GPIO_PTI4_MASK = (1<<4), /*!< GPIO Pin PTI4 bit mask */
|
||||
GPIO_PTI5_MASK = (1<<5), /*!< GPIO Pin PTI5 bit mask */
|
||||
GPIO_PTI6_MASK = (1<<6), /*!< GPIO Pin PTI6 bit mask */
|
||||
GPIO_PTI7_MASK = (1<<7), /*!< GPIO Pin PTI7 bit mask */
|
||||
} GPIO_PinMaskType;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义GPIO引脚配置类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*
|
||||
* . 如果引脚配置为输入,禁用高电流驱动
|
||||
* . 如果引脚配置为输出,禁用内部上拉
|
||||
* 仅PTH1/0, PTE1/0, PTD1/0, PTB5/4 支持高电流驱动.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GPIO_PinOutput = 0, /*!< 设置引脚为输出 */
|
||||
GPIO_PinInput, /*!< 设置引脚为输出*/
|
||||
GPIO_PinInput_InternalPullup, /*!< 设置引脚为输入且内部上拉 */
|
||||
GPIO_PinOutput_HighCurrent, /*!< 设置引脚为输出,高电流驱动*/
|
||||
} GPIO_PinConfigType;
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 切换FGPIO端口数据输出----通过32位掩码确定要切换输出的引脚
|
||||
*
|
||||
* @param[in] pGPIO 指向FGPIO模块, FGPIOA/FGPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码 ( GPIO_PTA0_MASK, GPIO_PTA1_MASK ............)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Toggle(FGPIO_Type *pFGPIO, uint32_t u32PinMask)
|
||||
{
|
||||
pFGPIO->PTOR = u32PinMask; /* 切换GPIO端口数据输出 */
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 读取FGPIO端口数据输入寄存器
|
||||
*
|
||||
* @param[in] pGPIO 指向FGPIO模块, FGPIOA/FGPIOB.
|
||||
*
|
||||
* @return FGPIO端口数据输入寄存器32值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint32_t FGPIO_Read(FGPIO_Type *pFGPIO)
|
||||
{
|
||||
return (pFGPIO->PDIR); /*读端口数据输入寄存器*/
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 写数据到FGPIO端口数据输出寄存
|
||||
*
|
||||
* @param[in] pGPIO 指向FGPIO模块, FGPIOA/FGPIOB.
|
||||
* @param[in] u32Value 写入的数值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Write(FGPIO_Type *pFGPIO, uint32_t u32Value)
|
||||
{
|
||||
pFGPIO->PDOR = u32Value; /*写数据到端口数据输出寄存器*/
|
||||
}
|
||||
|
||||
void GPIO_DeInit(GPIO_Type *pGPIO);
|
||||
void GPIO_Init(GPIO_Type *pGPIO, uint32_t u32PinMask, GPIO_PinConfigType sGpioType);
|
||||
void GPIO_Toggle(GPIO_Type *pGPIO, uint32_t u32PinMask);
|
||||
uint32_t GPIO_Read(GPIO_Type *pGPIO);
|
||||
void GPIO_Write(GPIO_Type *pGPIO, uint32_t u32Value);
|
||||
void GPIO_PinInit(GPIO_PinType GPIO_Pin, GPIO_PinConfigType GPIO_PinConfig);
|
||||
void GPIO_PinToggle(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinSet(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinClear(GPIO_PinType GPIO_Pin);
|
||||
uint8_t GPIO_BitRead(GPIO_PinType GPIO_Pin);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,347 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ICS 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef ICS_H_
|
||||
#define ICS_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/****************************************************************************!
|
||||
* @brief 时钟模式常量定义
|
||||
*
|
||||
***************************************************************************/
|
||||
enum
|
||||
{
|
||||
ICS_CLK_MODE_FEI = 1, /*!< FEI 模式 */
|
||||
ICS_CLK_MODE_FEE, /*!< FEE 模式 */
|
||||
ICS_CLK_MODE_FEE_OSC, /*!< FEE 模式 OSC输出时钟源选择来自EXTAL引脚的外部时钟源 */
|
||||
ICS_CLK_MODE_FBE, /*!< FBE 模式 */
|
||||
ICS_CLK_MODE_FBE_OSC, /*!< FBE 模式 OSC输出时钟源选择来自EXTAL引脚的外部时钟源 */
|
||||
ICS_CLK_MODE_FBI, /*!< FBI 模式 */
|
||||
ICS_CLK_MODE_FBILP, /*!< FBILP 模式 */
|
||||
ICS_CLK_MODE_FBELP, /*!< FBELP 模式 */
|
||||
};
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 将时钟模式从当前模式切换到另一个时钟模式.
|
||||
*
|
||||
* 时钟模式宏观定义如下:
|
||||
* FEI, FBI, FEE, FBE, FBILP, FBELP, FEE_OSC, FBE_OSC
|
||||
* 注:FEE_OSC, FBE_OSC 不能用作当前时钟模式. 当前时钟模式和要切换到的时钟模式组合如下:
|
||||
* < 当前时钟模式,要切换到的时钟模式>
|
||||
* <FEI,FEE>, <FEI,FBI>, <FEI,FBE>, <FEI,FBE_OSC>, <FEI,FEE_OSC>, <FEE,FEI>,
|
||||
* <FEE,FBI>, <FEE,FBE>, <FBI,FBE>, <FBI,FEE>, <FBI,FBILP>, <FBI,FEI>,
|
||||
* <FBE,FBI>, <FBE,FEE>, <FBE,FEI>, <FBE,FBELP>, <FBELP,FBE>, <FBILP,FBI>.
|
||||
*
|
||||
* @param[in] CurMode 当前时钟模式
|
||||
* @param[in] NewMode 要切换到的时钟模式
|
||||
* @param[in] clkFreq 参考时钟频率
|
||||
*
|
||||
* @return none
|
||||
* @warning FEE_OSC, FBE_OSC 不能用作当前时钟模式.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define ICS_SwitchMode(CurMode, NewMode, clkFreq) CurMode##_to_##NewMode(clkFreq)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 定义 OSC 配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bRange : 1; /*!< 1: 高频范围, 0: 低频范围 */
|
||||
uint8_t bGain : 1; /*!< 1: 高增益, 0:低增益 */
|
||||
uint8_t bEnable : 1; /*!< 1: 使能OSC, 0: 禁用OSC */
|
||||
uint8_t bStopEnable : 1; /*!< 1: 停止模式下OSC使能, 0: 停止模式下OSC禁用 */
|
||||
uint8_t bIsCryst : 1; /*!< 1: OSC输出选择振荡器时钟, 0: OSC输出选择来自extal引脚的外部时钟 */
|
||||
uint8_t bWaitInit : 1; /*!< 1: 等待振荡器初始化完成, 0: 不等待 */
|
||||
} OSC_ConfigType, *OSC_ConfigPtr;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ICS配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t u8ClkMode; /*!< 选择时钟模式*/
|
||||
uint8_t bLPEnable; /*!< 低功耗模式下使能 */
|
||||
uint32_t u32ClkFreq; /*!< 参考时钟频率 */
|
||||
OSC_ConfigType oscConfig; /*!< OSC 配置 */
|
||||
} ICS_ConfigType ;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能中断.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_DisableInt
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_EnableInt(void)
|
||||
{
|
||||
ICS->C4 |= (ICS_C4_LOLIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用中断
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_EnableInt
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_DisableInt(void)
|
||||
{
|
||||
ICS->C4 &= ~(ICS_C4_LOLIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能时钟监控
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_DisableClockMonitor
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_EnableClockMonitor(void)
|
||||
{
|
||||
ICS->C4 |= (ICS_C4_CME_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用时钟监控
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_EnableClockMonitor
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_DisableClockMonitor(void)
|
||||
{
|
||||
ICS->C4 &= ~(ICS_C4_CME_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ICS输出时钟源分频
|
||||
*
|
||||
* @param[in] busDivide -- 分频值
|
||||
*
|
||||
* @return depends on commands
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_SetBusDivider(uint8_t u8BusDivide)
|
||||
{
|
||||
ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(u8BusDivide);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能OSC
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_Enable(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_OSCEN_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用OSC
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_Disable(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_OSCEN_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置OSC模块的频率范围为低频范围
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetLowRange(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_RANGE_MASK);
|
||||
}
|
||||
|
||||
/*!***************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
*
|
||||
* @brief 设置OSC模块的频率范围为高频范围
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetHighRange(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_RANGE_MASK);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置OSC的工作模式为高增益模式
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetHighGain(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_HGO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置OSC的工作模式为低功耗模式
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetLowGain(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_HGO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择OSC模块的输出时钟源为振荡器时钟源
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SelectCrystal(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_OSCOS_MASK);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief OSC输出选择来自extal引脚的外部时钟
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SelectClock(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_OSCOS_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下OSC模块使能
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_ActiveInStop(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_OSCSTEN_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下OSC模块禁用
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_InactiveInStop(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_OSCSTEN_MASK);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ICS_Init(ICS_ConfigType *pConfig);
|
||||
void ICS_DeInit(void);
|
||||
void ICS_SetClkDivider(uint32_t u32ClkFreqKHz);
|
||||
void ICS_Trim(uint16 u16TrimValue);
|
||||
void OSC_Init(OSC_ConfigType *pConfig);
|
||||
void OSC_DeInit(void);
|
||||
|
||||
/************** 内联函数 ******************/
|
||||
void ICS_DisableClockMonitor(void);
|
||||
void ICS_DisableInt(void);
|
||||
void ICS_EnableClockMonitor(void);
|
||||
void ICS_EnableInt(void);
|
||||
void ICS_SetBusDivider(uint8_t u8BusDivide);
|
||||
void OSC_ActiveInStop(void);
|
||||
void OSC_Enable(void);
|
||||
void OSC_Disable(void);
|
||||
void OSC_InactiveInStop(void);
|
||||
void OSC_SelectClock(void);
|
||||
void OSC_SelectCrystal(void);
|
||||
void OSC_SetHighGain(void);
|
||||
void OSC_SetHighRange(void);
|
||||
void OSC_SetLowGain(void);
|
||||
void OSC_SetLowRange(void);
|
||||
|
||||
/* do not touch the following functions */
|
||||
void FEI_to_FEE(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FEE_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FEE_to_FEI(ICS_ConfigType *pConfig);
|
||||
void FEE_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FEE(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FEI(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FBELP(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FEI(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FEE(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FBILP(ICS_ConfigType *pConfig);
|
||||
void FBILP_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FBELP_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FBE_OSC(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FEE_OSC(ICS_ConfigType *pConfig);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,577 @@
|
||||
/*********************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file i2c.c
|
||||
* @brief i2c通讯接口函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
************************************************************************/
|
||||
#include "common.h"
|
||||
#include "i2c.h"
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
static I2C_CallbackType I2C_Callback[2] = {(I2C_CallbackType)NULL};
|
||||
|
||||
void I2C0_Isr( void );
|
||||
|
||||
/******************************************************************************
|
||||
* 定义I2C的接口函数
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化I2C模块.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] pI2CConfig 配置I2C的结构体.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void I2C_Init(I2C_Type *pI2Cx,I2C_ConfigPtr pI2CConfig)
|
||||
{
|
||||
uint8_t u8Temp;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SCGC |= SIM_SCGC_IIC_MASK;
|
||||
#endif
|
||||
|
||||
I2C_SetBaudRate(pI2Cx,pI2CConfig->u16F);
|
||||
I2C_SetSlaveAddress(pI2Cx,pI2CConfig->u16OwnA1);
|
||||
pI2Cx->FLT = (uint8_t)pI2CConfig->u16Filt;
|
||||
pI2Cx->RA = (uint8_t)pI2CConfig->u16RangeA & 0xfe;
|
||||
I2C_SetSCLLowETMeout(pI2Cx,pI2CConfig->u16Slt);
|
||||
|
||||
/* 配置控制寄存器C2 */
|
||||
u8Temp = 0;
|
||||
if( pI2CConfig->sSetting.bGCAEn )
|
||||
{
|
||||
u8Temp |= I2C_C2_GCAEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bAddressExt )
|
||||
{
|
||||
u8Temp |= I2C_C2_ADEXT_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bRangeAddEn )
|
||||
{
|
||||
u8Temp |= I2C_C2_RMEN_MASK;
|
||||
}
|
||||
pI2Cx->C2 |= u8Temp;
|
||||
|
||||
/* 配置寄存器SMB */
|
||||
u8Temp = 0;
|
||||
if( pI2CConfig->sSetting.bFackEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_FACK_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bSMB_AlertEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_ALERTEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bSecondAddressEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_SIICAEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bSHTF2IntEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_SHTF2IE_MASK;
|
||||
}
|
||||
pI2Cx->SMB = u8Temp;
|
||||
|
||||
/* 配置寄存器C1 */
|
||||
u8Temp = 0;
|
||||
if( pI2CConfig->sSetting.bIntEn )
|
||||
{
|
||||
u8Temp |= I2C_C1_IICIE_MASK;
|
||||
if(pI2Cx == I2C0)
|
||||
{
|
||||
NVIC_EnableIRQ(I2C0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
if( pI2CConfig->sSetting.bWakeUpEn )
|
||||
{
|
||||
u8Temp |= I2C_C1_WUEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bI2CEn )
|
||||
{
|
||||
u8Temp |= I2C_C1_IICEN_MASK;
|
||||
}
|
||||
pI2Cx->C1 = u8Temp;
|
||||
|
||||
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送I2C起始信号(启动传输).
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t I2C_Start(I2C_Type *pI2Cx)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
|
||||
I2C_TxEnable(pI2Cx);//将 I2C 配置成 TX 发送模式
|
||||
pI2Cx->C1 |= I2C_C1_MST_MASK;//将 I2C 配置成主机模式
|
||||
|
||||
//持续监测起始位有没有发送成功
|
||||
while( (!I2C_IsBusy(pI2Cx)) && ( u32ETMeout < I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
|
||||
if( u32ETMeout == I2C_WAIT_STATUS_ETMEOUT )
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_START_NO_BUSY_FLAG;
|
||||
}
|
||||
|
||||
return u8ErrorStatus;//返回错误标志,为0x10即起始信号没有发送成功
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送停止信号.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t I2C_Stop(I2C_Type *pI2Cx)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
|
||||
pI2Cx->C1 &= ~I2C_C1_MST_MASK;
|
||||
//持续监测 I2C 停止位是否发送成功
|
||||
while( (I2C_IsBusy(pI2Cx) ) && ( u32ETMeout < I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
|
||||
if( u32ETMeout == I2C_WAIT_STATUS_ETMEOUT )
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_STOP_BUSY_FLAG;
|
||||
}
|
||||
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送重复起始位.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 错误状态.
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t I2C_RepeatStart(I2C_Type *pI2Cx)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
|
||||
pI2Cx->C1 |= I2C_C1_RSTA_MASK;
|
||||
//持续监测起始位是否发送成功
|
||||
while( (!I2C_IsBusy(I2C0) ) && ( u32ETMeout < I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
|
||||
if( u32ETMeout == I2C_WAIT_STATUS_ETMEOUT )
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_START_NO_BUSY_FLAG;
|
||||
}
|
||||
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置从机地址.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] u16SlaveAddress 从机地址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_SetSlaveAddress(I2C_Type *pI2Cx,uint16_t u16SlaveAddress)
|
||||
{
|
||||
/* 写入8位地址 */
|
||||
pI2Cx->A1 = (uint8_t)u16SlaveAddress;
|
||||
|
||||
/* 如果支持十位从机地址, 写入高三位地址 */
|
||||
pI2Cx->C2 &= ~I2C_C2_AD_MASK;
|
||||
pI2Cx->C2 |= (uint8_t)(u16SlaveAddress>>8)&0x03;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用I2C中断.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_IntDisable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_IICIE_MASK;
|
||||
if(pI2Cx == I2C0)
|
||||
{
|
||||
NVIC_DisableIRQ(I2C0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能I2C中断.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_IntEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 |= I2C_C1_IICIE_MASK;
|
||||
if(pI2Cx == I2C0)
|
||||
{
|
||||
NVIC_EnableIRQ(I2C0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SCL低超时周期.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_SetSCLLowETMeout(I2C_Type *pI2Cx, uint16_t u16ETMeout)
|
||||
{
|
||||
pI2Cx->SLTL = (uint8_t)u16ETMeout;
|
||||
pI2Cx->SLTH = (uint8_t)(u16ETMeout>>8);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位I2C模块.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_Deinit(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_IICEN_MASK;
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SCGC &= ~SIM_SCGC_IIC_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送单字节数据.
|
||||
*
|
||||
* @param[in] pI2Cx I2C模块的基址.
|
||||
* @param[in] u8WrBuff 要写的数据缓冲区.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_WriteOneByte(I2C_Type *pI2Cx, uint8_t u8WrBuff)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_TCF_MASK) != I2C_S_TCF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_TCF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
I2C_TxEnable(pI2Cx); //将 I2C 配置成 TX 输出模式
|
||||
I2C_WriteDataReg(pI2Cx,u8WrBuff); //写数据寄存器发送数据
|
||||
|
||||
u32ETMeout = 0;
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_IICIF_MASK) != I2C_S_IICIF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_IICIF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
/* 清除中断标志位 */
|
||||
I2C_ClearStatus(pI2Cx,I2C_S_IICIF_MASK);
|
||||
if (I2C_GetStatus(pI2Cx) & I2C_S_RXAK_MASK)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_GET_ACK;
|
||||
}
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取单字节数据.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[out] pRdBuff 所要从从机读的地址.
|
||||
* @param[out] u8Ack 发送 ack or nack.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_ReadOneByte(I2C_Type *pI2Cx, uint8_t *pRdBuff, uint8_t u8Ack)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_TCF_MASK) != I2C_S_TCF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_TCF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
I2C_RxEnable(pI2Cx); //将 I2C 配置为输入模式
|
||||
|
||||
if( u8Ack )
|
||||
{
|
||||
/* 发送 nack */
|
||||
I2C_SendNack(pI2Cx);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 发送 ack */
|
||||
I2C_SendAck(pI2Cx);
|
||||
}
|
||||
*pRdBuff = I2C_ReadDataReg(pI2Cx); //将读到的数据存放到参数里头
|
||||
|
||||
u32ETMeout = 0;
|
||||
//持续监测中断标志
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_IICIF_MASK) != I2C_S_IICIF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_IICIF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
/*清除 IIC 中断标志位 */
|
||||
I2C_ClearStatus(pI2Cx,I2C_S_IICIF_MASK);
|
||||
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送数据到I2C,然后等待数据传送完成.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] u16SlaveAddress 16位从机地址.
|
||||
* @param[in] pWrBuff 需要发送数据的缓冲数组.
|
||||
* @param[in] u32Length 发送字节的数目.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_MasterSendWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pWrBuff,uint32_t u32Length)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
/* 发送起始信号 */
|
||||
u8ErrorStatus = I2C_Start(pI2Cx);
|
||||
|
||||
/* 给从机发送从机地址 */
|
||||
u8ErrorStatus = I2C_WriteOneByte(pI2Cx,((uint8_t)u16SlaveAddress<<1) | I2C_WRITE);
|
||||
|
||||
/* 如果没有错误发生, 则继续发送字节*/
|
||||
if( u8ErrorStatus == I2C_ERROR_NULL )
|
||||
{
|
||||
for(i=0;i<u32Length;i++)
|
||||
{
|
||||
u8ErrorStatus = I2C_WriteOneByte(pI2Cx,pWrBuff[i]);
|
||||
if( u8ErrorStatus != I2C_ERROR_NULL )
|
||||
{
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*发送 I2C 停止位 */
|
||||
u8ErrorStatus = I2C_Stop(pI2Cx);
|
||||
|
||||
return u8ErrorStatus;
|
||||
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取多个字节并等待完成.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] u16SlaveAddress 从机地址.
|
||||
* @param[in] pRdBuff 用于接收数据的缓冲区.
|
||||
* @param[in] u32Length 接收数据的字节数.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_MasterReadWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pRdBuff,uint32_t u32Length)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
/* 发送起始信号到总线 */
|
||||
u8ErrorStatus = I2C_Start(pI2Cx);
|
||||
|
||||
/* 给从机发送器件地址 */
|
||||
u8ErrorStatus = I2C_WriteOneByte(pI2Cx,((uint8_t)u16SlaveAddress<<1) | I2C_READ);
|
||||
|
||||
/* 如果没有错误发生, 则继续接收字节*/
|
||||
I2C_ReadOneByte(pI2Cx,&pRdBuff[0],I2C_SEND_ACK);
|
||||
|
||||
if( u8ErrorStatus == I2C_ERROR_NULL )
|
||||
{
|
||||
for(i=0;i<u32Length-1;i++)
|
||||
{
|
||||
u8ErrorStatus = I2C_ReadOneByte(pI2Cx,&pRdBuff[i],I2C_SEND_ACK);
|
||||
if( u8ErrorStatus != I2C_ERROR_NULL )
|
||||
{
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
}
|
||||
u8ErrorStatus = I2C_ReadOneByte(pI2Cx,&pRdBuff[i],I2C_SEND_NACK);
|
||||
}
|
||||
/*发送停止信号 */
|
||||
u8ErrorStatus = I2C_Stop(pI2Cx);
|
||||
|
||||
return u8ErrorStatus;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置I2C模块的中断回调函数
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void I2C1_SetCallBack( I2C_CallbackType pCallBack )
|
||||
{
|
||||
I2C_Callback[1] = pCallBack;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置RTC模块的中断回调函数
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void I2C0_SetCallBack( I2C_CallbackType pCallBack )
|
||||
{
|
||||
I2C_Callback[0] = pCallBack;
|
||||
}
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief I2C0 中断服务函数.
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C0_Isr( void )
|
||||
{
|
||||
if( I2C_Callback[0] )
|
||||
{
|
||||
I2C_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief I2C1 中断服务函数.
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C1_Isr( void )
|
||||
{
|
||||
if( I2C_Callback[1] )
|
||||
{
|
||||
I2C_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief I2C 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _I2C_H__
|
||||
#define _I2C_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* 定义I2C的读和写
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
#define I2C_READ 0x01 /*!< I2C 读 */
|
||||
#define I2C_WRITE 0x0 /*!< I2C 写 */
|
||||
/*! @} */
|
||||
|
||||
#define I2C_SEND_ACK 0 /*!< I2C 发送 ACK */
|
||||
#define I2C_SEND_NACK 1 /*!< I2C 发送 NACK */
|
||||
|
||||
#define I2C_WAIT_STATUS_ETMEOUT 200000
|
||||
|
||||
/******************************************************************************
|
||||
* 定义I2C错误状态
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
#define I2C_ERROR_NULL 0x00 /*!< I2C 工作成功*/
|
||||
#define I2C_ERROR_NO_WAIT_TCF_FLAG 0x01 /*!< I2C 等待传输完成超时*/
|
||||
#define I2C_ERROR_NO_WAIT_IICIF_FLAG 0x02 /*!< I2C 等待中断超时 */
|
||||
#define I2C_ERROR_NO_GET_ACK 0x04 /*!< I2C 没有得到 ACK */
|
||||
#define I2C_ERROR_START_NO_BUSY_FLAG 0x10 /*!< I2C 没有成功发送起始信号 */
|
||||
#define I2C_ERROR_STOP_BUSY_FLAG 0x20 /*!< I2C 没有成功发送停止信号 */
|
||||
#define I2C_ERROR_BUS_BUSY 0x80 /*!< I2C 总线繁忙错误 */
|
||||
/*! @} End of i2c_error_state_list */
|
||||
|
||||
/******************************************************************************
|
||||
* 定义I2C总线状态
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
#define I2C_BUS_NORMAL 0x00 /*!< I2C 总线正常 */
|
||||
#define I2C_BUS_SLTF 0x01 /*!< I2C 总线偏移一个FLAG */
|
||||
#define I2C_BUS_SHTF2 0x02 /*!< I2C 总线偏移两个FLAG */
|
||||
/*! @} */
|
||||
|
||||
|
||||
#define I2C_MODE_MASTER 1
|
||||
#define I2C_MODE_SLAVE 0
|
||||
#define I2C_ADDRESS_7BIT 0
|
||||
#define I2C_ADDRESS_10BIT 1
|
||||
#define I2C_ETMEOUT_BUS_CLOCK_DIV64 0
|
||||
#define I2C_ETMEOUT_BUS_CLOCK 1
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*//*! @I2C控制参数结构体
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @I2C控制参数结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bI2CEn :1; /*!< 使能I2C模块 */
|
||||
uint16_t bIntEn :1; /*!< 使能I2C中断 */
|
||||
uint16_t bWakeUpEn :1; /*!< I2C唤醒使能 */
|
||||
uint16_t bGCAEn :1; /*!< I2C通用启动地址使能 */
|
||||
uint16_t bAddressExt :1; /*!< I2C地址扩展选择 */
|
||||
uint16_t bRangeAddEn :1; /*!< 使能范围地址匹配 */
|
||||
uint16_t bFackEn :1; /*!< 使能快速ack */
|
||||
uint16_t bSMB_AlertEn :1; /*!< SMB 报警响应地址使能 */
|
||||
uint16_t bSecondAddressEn:1; /*!< 启用第二I2C地址 */
|
||||
uint16_t bETMeoutCountClockSelect:1; /*!< 超时计数器时钟选择 */
|
||||
uint16_t bSHTF2IntEn :1; /*!< SHTF2 中断使能 */
|
||||
uint16_t Reserve :5;
|
||||
}I2C_SettingType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*//*! @I2C配置结构体
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @I2C配置结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
I2C_SettingType sSetting;
|
||||
uint16_t u16F; /*!< 设置I2C模块的波特率 */
|
||||
uint16_t u16OwnA1; /*!< 从机地址 */
|
||||
uint16_t u16OwnA2; /*!< SMBus使用的从机地址 */
|
||||
uint16_t u16RangeA; /*!< 范围地址 */
|
||||
uint16_t u16Filt; /*!< I2C输入干扰滤波器 */
|
||||
uint16_t u16Slt; /*!< SCL低超时周期 */
|
||||
|
||||
}I2C_ConfigType, *I2C_ConfigPtr;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief I2C 回调类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef void (*I2C_CallbackType)(void);
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置I2C发送模式.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_TxEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置I2C接收模式.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_RxEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置I2C波特率.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SetBaudRate(I2C_Type *pI2Cx,uint32_t u32Bps)
|
||||
{
|
||||
pI2Cx->F = (uint8_t)u32Bps;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能通用地址启动.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_GeneralCallEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C2 |= I2C_C2_GCAEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SMBus 报警响应地址使能.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SMBusAlertEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->SMB|= I2C_SMB_ALERTEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 范围地址匹配使能.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_RangeAddressEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C2 |= I2C_C2_RMEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SHTF2 中断使能.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SHTF2IntEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SHTF2IE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 超时计数器时钟选择.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ETMeoutCounterClockSelect(I2C_Type *pI2Cx, uint8_t u8Clock)
|
||||
{
|
||||
if( u8Clock )
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_TCKSEL_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pI2Cx->SMB &= ~I2C_SMB_TCKSEL_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取I2C的状态.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return I2C的状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_GetStatus(I2C_Type *pI2Cx)
|
||||
{
|
||||
return pI2Cx->S;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除特定的状态.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ClearStatus(I2C_Type *pI2Cx, uint8_t u8ClearFlag)
|
||||
{
|
||||
pI2Cx->S |= u8ClearFlag;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写数据到数据寄存器.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_WriteDataReg(I2C_Type *pI2Cx, uint8_t u8DataBuff)
|
||||
{
|
||||
pI2Cx->D = u8DataBuff;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 从数据寄存器读取数据.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return I2C数据寄存器值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_ReadDataReg(I2C_Type *pI2Cx )
|
||||
{
|
||||
return pI2Cx->D;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查I2C模式是否为发送.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsTxMode(I2C_Type *pI2Cx )
|
||||
{
|
||||
return(pI2Cx->C1 & I2C_C1_TX_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查总线是否繁忙.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsBusy(I2C_Type *pI2Cx )
|
||||
{
|
||||
return (pI2Cx->S & I2C_S_BUSY_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 确认信号是否被接收.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsReceivedAck(I2C_Type *pI2Cx )
|
||||
{
|
||||
return (pI2Cx->S & I2C_S_RXAK_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查I2C是否为主机模式.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsMasterMode(I2C_Type *pI2Cx )
|
||||
{
|
||||
return(pI2Cx->C1 & I2C_C1_MST_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查有无低超时发生.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsSMB_SLTF(I2C_Type *pI2Cx )
|
||||
{
|
||||
return (pI2Cx->SMB & I2C_SMB_SLTF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查有无高超时发生.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsSMB_SHTF2(I2C_Type *pI2Cx )
|
||||
{
|
||||
return(pI2Cx->SMB & I2C_SMB_SHTF2_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除SCL低超时标志.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ClearSLTF(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SLTF_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除高超时标志位2.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ClearSHTF2(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SHTF2_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送信号ACK.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SendAck(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_TXAK_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送信号NACK.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SendNack(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->C1 |= I2C_C1_TXAK_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能第二I2C地址.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SecondAddressEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SIICAEN_MASK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
void I2C_Init(I2C_Type *pI2Cx,I2C_ConfigPtr pI2CConfig);
|
||||
uint8_t I2C_Start(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_Stop(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_RepeatStart(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_IsTxMode(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsBusy(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsReceivedAck(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsMasterMode(I2C_Type *pI2Cx );
|
||||
void I2C_ClearSHTF2(I2C_Type *pI2Cx );
|
||||
void I2C_ClearSLTF(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsSMB_SHTF2(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsSMB_SLTF(I2C_Type *pI2Cx );
|
||||
void I2C_TxEnable(I2C_Type *pI2Cx);
|
||||
void I2C_RxEnable(I2C_Type *pI2Cx);
|
||||
void I2C_IntEnable(I2C_Type *pI2Cx);
|
||||
void I2C_IntDisable(I2C_Type *pI2Cx);
|
||||
void I2C_SetBaudRate(I2C_Type *pI2Cx,uint32_t u32Bps);
|
||||
void I2C_SetSlaveAddress(I2C_Type *pI2Cx,uint16_t u16SlaveAddress);
|
||||
void I2C_GeneralCallEnable(I2C_Type *pI2Cx);
|
||||
void I2C_SMBusAlertEnable(I2C_Type *pI2Cx);
|
||||
void I2C_RangeAddressEnable(I2C_Type *pI2Cx);
|
||||
void I2C_SHTF2IntEnable(I2C_Type *pI2Cx);
|
||||
void I2C_ETMeoutCounterClockSelect(I2C_Type *pI2Cx, uint8_t u8Clock);
|
||||
void I2C_SetSCLLowETMeout(I2C_Type *pI2Cx, uint16_t u16ETMeout);
|
||||
uint8_t I2C_GetStatus(I2C_Type *pI2Cx);
|
||||
void I2C_ClearStatus(I2C_Type *pI2Cx, uint8_t u8ClearFlag);
|
||||
void I2C_SendAck(I2C_Type *pI2Cx );
|
||||
void I2C_SendNack(I2C_Type *pI2Cx );
|
||||
void I2C_SecondAddressEnable(I2C_Type *pI2Cx);
|
||||
void I2C_ClearStatus(I2C_Type *pI2Cx, uint8_t u8ClearFlag);
|
||||
void I2C_WriteDataReg(I2C_Type *pI2Cx, uint8_t u8DataBuff);
|
||||
uint8_t I2C_ReadDataReg(I2C_Type *pI2Cx );
|
||||
void I2C_Deinit(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_WriteOneByte(I2C_Type *pI2Cx, uint8_t u8WrBuff);
|
||||
uint8_t I2C_ReadOneByte(I2C_Type *pI2Cx, uint8_t *pRdBuff, uint8_t u8Ack);
|
||||
uint8_t I2C_MasterSendWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pWrBuff,uint32_t u32Length);
|
||||
uint8_t I2C_MasterReadWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pRdBuff,uint32_t u32Length);
|
||||
void I2C0_SetCallBack( I2C_CallbackType pCallBack );
|
||||
void I2C1_SetCallBack( I2C_CallbackType pCallBack );
|
||||
|
||||
/*! @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //
|
||||
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file kbi.c
|
||||
* @brief 键盘中断(KBI)函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "kbi.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放KBI回调函数接口
|
||||
****************************************************************************/
|
||||
KBI_CallbackType KBI_Callback[KBI_MAX_NO] = {(KBI_CallbackType)NULL};
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化KBI模块.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] pConfig 指向KBI配置结构体
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DeInit.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void KBI_Init(KBI_Type *pKBI, KBI_ConfigType *pConfig)
|
||||
{
|
||||
#if defined(CPU_NV32)
|
||||
uint16_t i;
|
||||
uint8_t sc = 0;
|
||||
uint8_t u8Port;
|
||||
uint8_t u8PinPos;
|
||||
uint16_t u16PinMapping[KBI_MAX_NO][8] =
|
||||
{
|
||||
{
|
||||
0, 1, 2, 3, 8, 9, 10, 11 /* KBI0中断输入引脚在GPIOA寄存器中的位置*/
|
||||
},
|
||||
{
|
||||
24, 25, 26, 27, 28, 29, 30, 31 /*KBI1中断输入引脚在GPIOA寄存器中的位置*/
|
||||
}
|
||||
};
|
||||
#elif defined(CPU_NV32M3)
|
||||
uint16_t i;
|
||||
uint8_t sc = 0;
|
||||
uint8_t u8Port;
|
||||
uint8_t u8PinPos;
|
||||
uint16_t u16PinMapping[KBI_MAX_NO][8] =
|
||||
{
|
||||
{
|
||||
0, 1, 2, 3, 8, 9, 10, 11 /* KBI0中断输入引脚在GPIOA寄存器中的位置*/
|
||||
},
|
||||
{
|
||||
20, 21, 16, 17, 18, 19, 12, 13 /* KBI1中断输入引脚在GPIOA寄存器中的位置*/
|
||||
}
|
||||
};
|
||||
#elif defined(CPU_NV32M4)
|
||||
uint32_t i;
|
||||
uint32_t sc = 0;
|
||||
uint32_t u8Port;
|
||||
uint32_t u8PinPos;
|
||||
|
||||
uint32_t u16PinMapping[KBI_MAX_NO][KBI_MAX_PINS_PER_PORT] =
|
||||
{
|
||||
{/* KBI0P0~KBI0P31 中断输入引脚在GPIOA寄存器中的位置 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
},
|
||||
{/* KBI1P0~KBI1P31中断输入引脚在GPIOA寄存器中的位置 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_KBI0_MASK; /* 使能KBI0模块的总线时钟 */
|
||||
u8Port = 0;
|
||||
}
|
||||
else if (KBI1 == pKBI)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_KBI1_MASK; /* 使能KBI1模块的总线时钟 */
|
||||
u8Port = 1;
|
||||
}
|
||||
|
||||
/*设定KBI中断检测模式*/
|
||||
sc = pConfig->sBits.bMode;
|
||||
pKBI->SC = sc;
|
||||
|
||||
/* 配置KBI中断输入引脚 */
|
||||
for (i = 0; i < KBI_MAX_PINS_PER_PORT; i++)
|
||||
{
|
||||
if(pConfig->sPin[i].bEn)
|
||||
{
|
||||
pKBI->PE |= (1<<i); /* 使能I/O引脚为KBI中断输入引脚*/
|
||||
pKBI->ES = (pKBI->ES & ~(1<<i)) | (pConfig->sPin[i].bEdge << i);
|
||||
u8PinPos = u16PinMapping[u8Port][i];
|
||||
ASSERT(!(u8PinPos & 0x80));
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
FGPIOA->PIDR &= ~(1<<u8PinPos); /* 使能GPIO输入*/
|
||||
FGPIOA->PDDR &= ~(1<<u8PinPos); /* 引脚配置为通用输入 */
|
||||
PORT->PUEL |= (1<<u8PinPos); /* 使能内部上拉*/
|
||||
#elif defined(CPU_NV32M4)
|
||||
if (u8Port == 0) /* KBI0 */
|
||||
{
|
||||
FGPIOA->PIDR &= ~(1<<u8PinPos); /* 使能GPIO输入*/
|
||||
FGPIOA->PDDR &= ~(1<<u8PinPos); /* 引脚配置为通用输入 */
|
||||
PORT->PUE0 |= (1<<u8PinPos); /* 使能内部上拉*/
|
||||
}
|
||||
else if (u8Port == 1) /* KBI1 */
|
||||
{
|
||||
FGPIOB->PIDR &= ~(1<<u8PinPos); /* 使能GPIO输入*/
|
||||
FGPIOB->PDDR &= ~(1<<u8PinPos); /* 引脚配置为通用输入 */
|
||||
PORT->PUE1 |= (1<<u8PinPos); /* 使能内部上拉*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CPU_NV32M4)
|
||||
/*Reset KBI_SP register*/
|
||||
sc = pConfig->sBits.bRstKbsp<<KBI_SC_RSTKBSP_SHIFT;
|
||||
pKBI->SC |= sc;
|
||||
|
||||
/*Real KBI_SP register enable*/
|
||||
sc = pConfig->sBits.bKbspEn<<KBI_SC_KBSPEN_SHIFT;
|
||||
pKBI->SC |= sc;
|
||||
#endif
|
||||
|
||||
/*清除中断标志位*/
|
||||
pKBI->SC = sc;
|
||||
|
||||
/* 使能KBI中断 */
|
||||
if(pConfig->sBits.bIntEn)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBIE_MASK;
|
||||
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
NVIC_EnableIRQ(KBI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(KBI1_IRQn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置KBI回调函数,通过中断服务函数调用
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] pfnCallback 指向回调函数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void KBI_SetCallback(KBI_Type *pKBI, KBI_CallbackType pfnCallback)
|
||||
{
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
KBI_Callback[0] = pfnCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
KBI_Callback[1] = pfnCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位KBI模块.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_Init.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void KBI_DeInit(KBI_Type *pKBI)
|
||||
{
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
NVIC_DisableIRQ(KBI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(KBI1_IRQn);
|
||||
}
|
||||
|
||||
pKBI->PE = 0;
|
||||
pKBI->SC = 0;
|
||||
pKBI->ES = 0;
|
||||
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_KBI0_MASK; /* 禁用KBI0模块总线时钟 */
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_KBI1_MASK; /* 禁用KBI1模块总线时钟 */
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief KBI0模块中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void KBI0_Isr(void)
|
||||
{
|
||||
KBI0->SC |= KBI_SC_KBACK_MASK; /*清除中断标志位 */
|
||||
|
||||
if(KBI_Callback[0])
|
||||
{
|
||||
KBI_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief KBI1模块中断服务函数
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void KBI1_Isr(void)
|
||||
{
|
||||
KBI1->SC |= KBI_SC_KBACK_MASK; /*清除中断标志位*/
|
||||
|
||||
if(KBI_Callback[1])
|
||||
{
|
||||
KBI_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief KBI 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _KBI_H_
|
||||
#define _KBI_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/********************************************************!
|
||||
*
|
||||
* @brief KBI模块中断输入信号检测模式选择
|
||||
*
|
||||
***********************************************************/
|
||||
typedef enum
|
||||
{
|
||||
KBI_MODE_EDGE_ONLY = 0, /*!< 选择 边沿检测 */
|
||||
KBI_MODE_EDGE_LEVEL /*!< 选择 边沿和电平检测*/
|
||||
}KBI_ModeType;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KBI_FALLING_EDGE_LOW_LEVEL = 0, /*!< 选择 下降沿或低电平 */
|
||||
KBI_RISING_EDGE_HIGH_LEVEL /*!< 选择 上升沿或高电平 */
|
||||
}KBI_EdgeType;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义KBI模块个数和中断输入引脚个数
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define KBI_MAX_NO 2 /*!< KBI模块个数 */
|
||||
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
#define KBI_MAX_PINS_PER_PORT 8 /*!< KBI中断输入引脚个数 */
|
||||
#elif defined(CPU_NV32M4)
|
||||
#define KBI_MAX_PINS_PER_PORT 32 /*!< KBI中断输入引脚个数 */
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* KBI回调函数声明
|
||||
******************************************************************************/
|
||||
typedef void (*KBI_CallbackType)(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* KBI引脚配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bEdge : 1; /*!< 边沿/电平选择为*/
|
||||
uint8_t bEn : 1; /*!< 引脚使能位*/
|
||||
uint8_t bRsvd : 6; /*!< 保留 */
|
||||
} KBI_PinConfigType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* KBI配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief KBI状态和控制寄存器结构体.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
struct
|
||||
{
|
||||
uint8_t bMode : 1; /*!< 选择KBI检测模式 */
|
||||
uint8_t bIntEn : 1; /*!< 使能KBI中断位 */
|
||||
uint8_t bRsvd : 6; /*!< 保留 */
|
||||
} sBits;
|
||||
#elif defined(CPU_NV32M4)
|
||||
struct
|
||||
{
|
||||
uint32_t bMode : 1; /*!< 选择KBI检测模式 */
|
||||
uint32_t bIntEn : 1; /*!< 使能KBI中断位 */
|
||||
uint32_t bRsvd2 : 2; /*!< 保留 */
|
||||
uint32_t bKbspEn : 1; /*!<Real KBI_SP register enable*/
|
||||
uint32_t bRstKbsp: 1; /*!<Reset KBI_SP register*/
|
||||
uint32_t bRsvd26 : 26; /*!< reserved */
|
||||
} sBits;
|
||||
#endif
|
||||
KBI_PinConfigType sPin[KBI_MAX_PINS_PER_PORT];
|
||||
} KBI_ConfigType, *KBI_ConfigTypePtr;
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置仅下降沿检测.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DetectRisingEdge.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdge(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdge(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC &= ~KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES &= ~(PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置仅高电平检测
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DetectFallingEdge.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdge(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdge(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC &= ~KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES |= (PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置上升沿和高电平检测
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DetectFallingEdgeLowLevel.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdgeHighLevel(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdgeHighLevel(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES |= (PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置下降沿和低电平检测
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none.
|
||||
*
|
||||
* @see KBI_DetectRisingEdgeHighLevel.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdgeLowLevel(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdgeLowLevel(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES &= ~(PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能KBI中断输入引脚
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块..
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_Disable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_Enable(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_Enable(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->PE |= (PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用KBI中断输入引脚.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块..
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_Enable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_Disable(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_Disable(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->PE &= ~(PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能KBI中断
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块..
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see KBI_DisableInt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_EnableInt(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBIE_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用KBI中断
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see KBI_EnableInt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_DisableInt(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC &= ~KBI_SC_KBIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取中断标志位
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return uint8_t.
|
||||
*
|
||||
* @see KBI_ClrFlags.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE uint8_t KBI_GetFlags(KBI_Type *pKBI)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE uint32_t KBI_GetFlags(KBI_Type *pKBI)
|
||||
#endif
|
||||
{
|
||||
return (pKBI->SC & KBI_SC_KBF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除中断标志位.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see KBI_GetFlags.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_ClrFlags(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBACK_MASK;
|
||||
}
|
||||
|
||||
#if defined(CPU_NV32M4)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Real KBI_SP register enable.
|
||||
*
|
||||
* @param[in] pKBI pointer to KBI module
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*
|
||||
* @see The real ETMe value of Keyboard source pin to be read.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_SPEnable(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBSPEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Get KBI source pin register fields.
|
||||
*
|
||||
* @param[in] pKBI pointer to KBI module.
|
||||
*
|
||||
* @return uint32_t.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none.
|
||||
*
|
||||
* @see KBI_GetSP.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint32_t KBI_GetSP(KBI_Type *pKBI)
|
||||
{
|
||||
return (pKBI->SP & KBI_SP_SP_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Reset KBI_SP register.
|
||||
*
|
||||
* @param[in] pKBI pointer to KBI module
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*
|
||||
* @see KBI_RstSP.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_RstSP(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_RSTKBSP_MASK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Global functions
|
||||
******************************************************************************/
|
||||
|
||||
void KBI_Init(KBI_Type *pKBI, KBI_ConfigType *pConfig);
|
||||
void KBI_SetCallback(KBI_Type *pKBI, KBI_CallbackType pfnCallback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,317 @@
|
||||
/*!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file flash.c
|
||||
* @brief flash函数库
|
||||
* @author Navota
|
||||
* @date 2018-6-19
|
||||
*/
|
||||
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
#define FLASH_ENABLE_STALLING_FLASH_CONTROLLER
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: Flash_Init
|
||||
*
|
||||
* @brief 初始化FLASH
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint16_t Flash_Init(void)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
uint32_t clkDIV = BUS_CLK_HZ/1000000L - 1;
|
||||
uint32_t Tpgs =(285 *(BUS_CLK_HZ/100))/1000000L; //update 2016.8.4 by 光脚板のGG
|
||||
uint32_t Tprog =(675*(BUS_CLK_HZ/100))/1000000L; //by 光脚板のGG
|
||||
|
||||
|
||||
EFMCR=(clkDIV<<24) + 0x00000001; //divide to 1M hz
|
||||
EFMETM0=(Tpgs<<16) + 0x00001194; //0x00281194; //
|
||||
EFMETM1=(Tprog<<16) + 0x000088B8; //
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: FlashProgram
|
||||
*
|
||||
* @brief flash加载编程:总的过程就是,给出字节长度,先写入满足两个字的个数,
|
||||
* 再写入剩余满足一个字的个数,最后写入剩余的字节数。
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
|
||||
* @param[in] *pData 所要存放的数据
|
||||
* @param[in] sizeBytes 字节长度
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__ramfunc uint16_t Flash_Program(uint32_t wNVMTargetAddress, uint8_t *pData, uint16_t sizeBytes)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
uint16_t w2LongWordCount = sizeBytes>>3;//处理一下,得到2个字的个数
|
||||
uint8_t wLeftBytes = (sizeBytes & 0x07);//低位三个字节的个数
|
||||
uint16_t wLeftLongWords = wLeftBytes>>2;//低位中满一个字个数
|
||||
uint32_t wTargetAddress = wNVMTargetAddress;
|
||||
uint32_t dwData0,dwData1;
|
||||
uint32_t *pdwData = (uint32_t*)pData;//传参
|
||||
int i;
|
||||
//判断是否字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);//返回无效的参数
|
||||
}
|
||||
//循环写入两个长字(即8个字节),共写入w2LongWordCount * 8个字节
|
||||
for(i = 0; i < w2LongWordCount; i++)
|
||||
{
|
||||
dwData0 = *pdwData++;
|
||||
dwData1 = *pdwData++;
|
||||
err = Flash_Program2LongWords(wTargetAddress, dwData0, dwData1);//加载两个字的编程
|
||||
if(err) //地址不为4个字节对齐,则直接跳转
|
||||
{
|
||||
goto EndP;
|
||||
//break;
|
||||
}
|
||||
wTargetAddress += 8;//循环一次写入8个字节,即2个字,NV32的flash是字对齐的
|
||||
}
|
||||
// 一个字的编程,即4bytes
|
||||
for(i = 0; i < wLeftLongWords; i++)
|
||||
{
|
||||
dwData0 = *pdwData++;
|
||||
err = Flash_Program1LongWord(wTargetAddress, dwData0);
|
||||
if(err)
|
||||
{
|
||||
goto EndP;
|
||||
//break;
|
||||
}
|
||||
wTargetAddress += 4;
|
||||
}
|
||||
wLeftBytes = (wLeftBytes-(wLeftLongWords<<2)); //在两字和一字的编程都处理完后剩余的低两位字节数
|
||||
if(!wLeftBytes){ //若无剩余字节数,返回成功
|
||||
return (err);
|
||||
}
|
||||
|
||||
#if defined(BIG_ENDIAN)
|
||||
dwData0 = 0;
|
||||
pData = (uint8_t*)pdwData;
|
||||
for(i = wLeftBytes; i >0; i--)
|
||||
{
|
||||
dwData0 <<= 8;
|
||||
dwData0 |= *pData++;
|
||||
}
|
||||
|
||||
wLeftBytes = 4 - wLeftBytes;
|
||||
for(i = wLeftBytes; i >0; i--)
|
||||
{
|
||||
dwData0 <<= 8;
|
||||
dwData0 |= 0xFF;
|
||||
}
|
||||
#else
|
||||
dwData0 = 0xFFFFFFFFL;
|
||||
pData = (uint8_t*)pdwData+wLeftBytes-1;
|
||||
for(i = wLeftBytes; i >0; i--)
|
||||
{
|
||||
dwData0 <<= 8;
|
||||
dwData0 |= *pData--;
|
||||
}
|
||||
#endif
|
||||
err = Flash_Program1LongWord(wTargetAddress, dwData0);
|
||||
EndP:
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
|
||||
* @function name: FlashProgram1LongWord
|
||||
*
|
||||
* @brief 加载一个字的大小,编程到FLASH中(也就是四个字节)
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
|
||||
* @param[in] dwData 所要存放的数据
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t Flash_Program1LongWord(uint32_t wNVMTargetAddress, uint32_t dwData)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
//判断是否为字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
// 清除错误标志
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
//写入数据到对应的地址中
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = dwData;
|
||||
//加载编程命令
|
||||
EFM_LaunchCMD(FLASH_CMD_PROGRAM);
|
||||
EnableInterrupts;
|
||||
return (err);//返回状态
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
|
||||
* @function name: FlashProgram2LongWords
|
||||
*
|
||||
* @brief 加载两个字的大小,编程到FLASH中(也就是八个字节)
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
|
||||
* @param[in] dwData0 低4个字节
|
||||
* @param[in] dwData1 高4个字节
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t Flash_Program2LongWords(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
|
||||
//判断是否为字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
// 清除错误标志
|
||||
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = dwData0;//存放数据到以目标地址为起始的4个字节的空间中
|
||||
EFM_LaunchCMD(FLASH_CMD_PROGRAM);//0x20000000,加载编程命令
|
||||
EnableInterrupts;
|
||||
wNVMTargetAddress = wNVMTargetAddress +4;//地址是字对齐的,地址向后移一个字
|
||||
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = dwData1;//第二个数据放入处理后的地址的4个字节的空间中
|
||||
EFM_LaunchCMD(FLASH_CMD_PROGRAM);//加载编程命令
|
||||
EnableInterrupts;
|
||||
return (err);//返回处理状态
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: Flash_EraseSector
|
||||
*
|
||||
* @brief 擦除目标地址的一个扇区(512字节),.
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 擦除扇区的首地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t Flash_EraseSector(uint32_t wNVMTargetAddress)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
// 判断是否字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
// 清除错误标志
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = 0xffffffff;
|
||||
EFM_LaunchCMD(FLASH_CMD_ERASE_SECTOR);//加载擦除命令
|
||||
EnableInterrupts;
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
__ramfunc uint16_t Flash_VerifyBackdoorKey()
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
// Clear error flags
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
// Write index to specify the command code to be loaded
|
||||
Custombkd = FLASH_FACTORY_KEY;
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: NVM_EraseAll
|
||||
*
|
||||
* @brief 整片擦除FLASH(慎用,注意0X40E这个地址,在调试阶段写入0XFE)
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t NVM_EraseAll(void)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
EFM_LaunchCMD(FLASH_CMD_ERASE_ALL);
|
||||
// Clear error flags
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: NVM_Unsecure
|
||||
*
|
||||
* @brief unsecure
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t NVM_Unsecure(void)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: EFM_LaunchCMD
|
||||
*
|
||||
* @brief 命令加载函数(注:此函数须放入SRAM中运行)
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef IAR
|
||||
void __ramfunc EFM_LaunchCMD(uint32_t EFM_CMD)
|
||||
#else
|
||||
__ramfunc void EFM_LaunchCMD(uint32_t EFM_CMD)
|
||||
#endif
|
||||
{
|
||||
DisableInterrupts;
|
||||
if((EFMCMD&EFM_DONE_MASK)== EFM_STATUS_READY)
|
||||
{
|
||||
EFMCMD = EFM_CMD;
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
if((EFMCMD&EFM_DONE_MASK) == EFM_STATUS_DONE) break;
|
||||
}
|
||||
EnableInterrupts;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief FLASH Çý¶¯Í·Îļþ.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef FLASH_H_
|
||||
#define FLASH_H_
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define ETMRH_FSTAT_MGSTAT0_MASK (1)
|
||||
#define ETMRH_FSTAT_MGSTAT1_MASK (1<<1)
|
||||
|
||||
#define FLASH_SECTOR_SIZE 512 // in bytes
|
||||
|
||||
#define FLASH_ERR_BASE 0x3000
|
||||
#define FLASH_ERR_SUCCESS 0
|
||||
#define FLASH_ERR_INVALID_PARAM (FLASH_ERR_BASE+1)
|
||||
#define EEPROM_ERR_SINGLE_BIT_FAULT (FLASH_ERR_BASE+2)
|
||||
#define EEPROM_ERR_DOUBLE_BIT_FAULT (FLASH_ERR_BASE+4)
|
||||
#define FLASH_ERR_ACCESS (FLASH_ERR_BASE+8)
|
||||
#define FLASH_ERR_PROTECTION (FLASH_ERR_BASE+0x10)
|
||||
#define FLASH_ERR_MGSTAT0 (FLASH_ERR_BASE+0x11)
|
||||
#define FLASH_ERR_MGSTAT1 (FLASH_ERR_BASE+0x12)
|
||||
#define FLASH_ERR_INIT_CCIF (FLASH_ERR_BASE+0x14)
|
||||
#define FLASH_ERR_INIT_FDIV (FLASH_ERR_BASE+0x18)
|
||||
|
||||
/*********************************/
|
||||
|
||||
#define FLASH_CMD_PROGRAM 0x20000000
|
||||
#define FLASH_CMD_CLEAR 0x00005000
|
||||
#define FLASH_CMD_ERASE_ALL 0x41000000
|
||||
#define FLASH_CMD_ERASE_SECTOR 0x40000000
|
||||
#define FLASH_FACTORY_KEY 0x00cfbdbe
|
||||
|
||||
#define EFM_DONE_MASK 0x00006000
|
||||
#define EFM_STATUS_DONE 0x00006000
|
||||
#define EFM_STATUS_READY 0x00002000
|
||||
|
||||
#define FLASH_ACCERR_MASK 0x10
|
||||
|
||||
#define M8(adr) (*((volatile unsigned char *) (adr)))
|
||||
#define M16(adr) (*((volatile unsigned short *) (adr)))
|
||||
#define M32(adr) (*((volatile unsigned long *) (adr)))
|
||||
|
||||
#define __ramfunc __attribute__ ((long_call, section (".ramfunctions")))
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
typedef uint16_t (*TFlash_Fun1)(uint32_t wNVMTargetAddress, uint8_t *pbData, uint8_t bByteCount);
|
||||
typedef uint16_t (*TFlash_Fun2)(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1);
|
||||
typedef uint16_t (*TFlash_Fun3)(uint32_t wNVMTargetAddress, uint32_t dwData);
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
__ramfunc uint16_t Flash_Program(uint32_t wNVMTargetAddress, uint8_t *pData, uint16_t sizeBytes);
|
||||
__ramfunc uint16_t Flash_Program1LongWord(uint32_t wNVMTargetAddress, uint32_t dwData);
|
||||
__ramfunc uint16_t Flash_Program2LongWords(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1);
|
||||
|
||||
__ramfunc uint16_t Flash_EraseSector(uint32_t wNVMTargetAddress);
|
||||
|
||||
__ramfunc uint16_t Flash_VerifyBackdoorKey(void);
|
||||
|
||||
__ramfunc uint16_t NVM_EraseAll(void);
|
||||
|
||||
__ramfunc uint16_t NVM_Unsecure(void);
|
||||
|
||||
uint16_t Flash_Init(void);
|
||||
|
||||
#ifdef IAR
|
||||
void __ramfunc EFM_LaunchCMD(uint32_t EFM_CMD);
|
||||
#else
|
||||
__ramfunc void EFM_LaunchCMD(uint32_t EFM_CMD);
|
||||
#endif
|
||||
|
||||
|
||||
void Flash_CopyInRAM(void);
|
||||
void Flash_CopyRouinte2RAM(char *func, uint16_t sizeFunc);
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* FLASH_H_ */
|
||||
@@ -0,0 +1,41 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Navota Microelectronics Inc. Navota Camels 32 Bit MCU
|
||||
* (c) Copyright 2015-2016 Navota Microelectronics, Inc.
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* @file flash_cmd.c
|
||||
*
|
||||
* @brief application entry point which performs application specific tasks.
|
||||
*
|
||||
*******************************************************************************
|
||||
*
|
||||
* provide a demo for how to initialize the NV32, output messages via SCI,
|
||||
* flash operations, etc.
|
||||
* NOTE:
|
||||
* printf call may occupy a lot of memory (around 1924 bytes), so please
|
||||
* consider your code size before using printf.
|
||||
******************************************************************************
|
||||
*
|
||||
* provide FLASH driver
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
void EFM_LaunchCMD(uint32_t EFM_CMD)
|
||||
{
|
||||
#define DisableInterrupts£»
|
||||
if((EFMCMD&EFM_DONE_MASK)== EFM_STATUS_READY)
|
||||
{
|
||||
EFMCMD = EFM_CMD;
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
if((EFMCMD&EFM_DONE_MASK) == EFM_STATUS_DONE) break;
|
||||
}
|
||||
#define EnableInterrupts;
|
||||
__asm("nop");
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file pit.c
|
||||
* @brief pit定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "pit.h"
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
PIT_CallbackType PIT_Callback[2] = {(PIT_CallbackType)NULL};
|
||||
|
||||
void PIT_Ch0Isr(void);
|
||||
void PIT_Ch1Isr(void);
|
||||
|
||||
/******************************************************************************
|
||||
* 定义PIT的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化PIT模块.
|
||||
*
|
||||
* @param[in] u8Channel_No 通道号
|
||||
* @param[in] pConfig 配置模块的结构体指针
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_Init(uint8_t u8Channel_No, PIT_ConfigType *pConfig)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_PIT_MASK; /*!< 选通PIT模块门控时钟 */
|
||||
|
||||
if (pConfig->bFreeze)
|
||||
{
|
||||
PIT_SetDebugFreeze();
|
||||
}
|
||||
|
||||
if (pConfig->bModuleDis == 0)
|
||||
{
|
||||
PIT_Enable(); /*!< 标准PIT定时器的时钟使能 */
|
||||
}
|
||||
|
||||
PIT_SetLoadVal(u8Channel_No, pConfig->u32LoadValue); //加载对应通道的定时器起始值
|
||||
|
||||
if (pConfig->bInterruptEn)
|
||||
{
|
||||
if (u8Channel_No)
|
||||
{
|
||||
NVIC_EnableIRQ(PIT_CH1_IRQn); //开启对应通道IRQ中断
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(PIT_CH0_IRQn);
|
||||
}
|
||||
PIT_ChannelEnableInt(u8Channel_No); //开启对应通道的中断请求
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(PIT_CH0_IRQn); //禁止通道0的IRQ中断
|
||||
}
|
||||
|
||||
if (pConfig->bChainMode)
|
||||
{
|
||||
PIT_ChannelEnableChain(u8Channel_No); //定时器链接到前一定时器
|
||||
}
|
||||
|
||||
if (pConfig->bETMerEn)
|
||||
{
|
||||
PIT_ChannelEnable(u8Channel_No); //定时器通道使能
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 装载定时器起始值到加载值寄存器中.
|
||||
*
|
||||
* @param[in] u8Channel_No 通道号
|
||||
* @param[in] u32loadvalue 所有加载的数值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_SetLoadVal(uint8_t u8Channel, uint32_t u32loadvalue)
|
||||
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].LDVAL = u32loadvalue;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置PIT模块回调函数.
|
||||
*
|
||||
* @param[in] u8Channel_No 通道号.
|
||||
* @param[in] pfnCallback 指向回调函数.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_SetCallback(uint8_t u8Channel_No, PIT_CallbackType pfnCallback)
|
||||
{
|
||||
PIT_Callback[u8Channel_No] = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位PIT模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_DeInit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(PIT_CH0_IRQn);
|
||||
NVIC_DisableIRQ(PIT_CH1_IRQn);
|
||||
PIT_SetLoadVal(0,0);
|
||||
PIT_SetLoadVal(1,0);
|
||||
PIT_ChannelDisable(0);
|
||||
PIT_ChannelDisable(1);
|
||||
PIT_ChannelDisableInt(0);
|
||||
PIT_ChannelDisableInt(1);
|
||||
PIT_ChannelDisableChain(0);
|
||||
PIT_ChannelDisableChain(1);
|
||||
PIT_ChannelClrFlags(0);
|
||||
PIT_ChannelClrFlags(1);
|
||||
PIT_SetDebugOn();
|
||||
PIT_Disable();
|
||||
SIM->SCGC &= ~SIM_SCGC_PIT_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PIT0通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_Ch0Isr(void)
|
||||
{
|
||||
PIT_ChannelClrFlags(0); //清除中断标志位
|
||||
|
||||
if (PIT_Callback[0])
|
||||
{
|
||||
PIT_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PIT0通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_Ch1Isr(void)
|
||||
{
|
||||
PIT_ChannelClrFlags(1); //清除中断标志位
|
||||
if (PIT_Callback[1])
|
||||
{
|
||||
PIT_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief PIT 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef PIT_H_
|
||||
#define PIT_H_
|
||||
#include"common.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PIT 通道号列表
|
||||
*
|
||||
*//*!
|
||||
*******************************************************************************/
|
||||
enum
|
||||
{
|
||||
PIT_CHANNEL0 = 0, /*!< PIT 通道 0 */
|
||||
PIT_CHANNEL1 /*!< PIT 通道 1 */
|
||||
};
|
||||
|
||||
/*! */
|
||||
|
||||
|
||||
/*!
|
||||
* @brief PIT 回调类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef void (*PIT_CallbackType)(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* PIT 配置结构体体
|
||||
*/
|
||||
/*!
|
||||
* @brief PIT 配置参数.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bFreeze : 1; /*!< 1: 在调试模式时冻结, 0: 在调试模式时仍然运行 */
|
||||
uint8_t bModuleDis : 1; /*!< 1: 禁用PIT模块, 0: 使能PIT模块 */
|
||||
uint8_t bReserved0 : 1; /*!< 保留 */
|
||||
uint8_t bReserved1 : 5; /*!< 保留 */
|
||||
uint8_t bETMerEn : 1; /*!< 1: 使能PIT通道, 0: 禁止PIT通道 */
|
||||
uint8_t bInterruptEn : 1; /*!< 1: 使能PIT通道中断, 0: 禁止PIT通道中断 */
|
||||
uint8_t bChainMode : 1; /*!< 1: 使能链模式, 0: 禁止链模式 */
|
||||
uint8_t bReserved2 : 5; /*!< 保留 */
|
||||
uint8_t bFlag : 1; /*!< 1: PIT中断标志位置位,写1清0, 0: PIT中断标志位没有置位 */
|
||||
uint8_t bReserved3 : 7; /*!< 保留 */
|
||||
uint32_t u32LoadValue ; /*!< 32位通道加载模值 */
|
||||
} PIT_ConfigType, *PIT_ConfigPtr;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能PIT模块.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_Enable(void)
|
||||
{
|
||||
|
||||
PIT->MCR &= ~PIT_MCR_MDIS_MASK;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT模块.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_Disable(void)
|
||||
{
|
||||
|
||||
PIT->MCR |= PIT_MCR_MDIS_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置PIT在调试模式下禁止运行.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_SetDebugFreeze(void)
|
||||
{
|
||||
|
||||
PIT->MCR |= PIT_MCR_FRZ_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置PIT在调试模式下继续运行.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_SetDebugOn(void)
|
||||
{
|
||||
|
||||
PIT->MCR &= ~PIT_MCR_FRZ_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PIT定时器通道使能.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelEnable(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL |= PIT_TCTRL_TEN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT定时器通道.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelDisable(uint8_t u8Channel)
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL &= ~PIT_TCTRL_TEN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能PIT定时器通道中断.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelEnableInt(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL |= PIT_TCTRL_TIE_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT定时器通道中断.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelDisableInt(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL &= ~PIT_TCTRL_TIE_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能PIT定时器通道链模式.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelEnableChain(uint8_t u8Channel)
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].TCTRL |= PIT_TCTRL_CHN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT定时器通道链模式.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelDisableChain(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].TCTRL &= ~PIT_TCTRL_CHN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取PIT通道中断标志位.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return PIT通道中断标志位.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t PIT_ChannelGetFlags(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
uint8_t bflag;
|
||||
|
||||
bflag = (PIT->CHANNEL[u8Channel].TFLG & PIT_TFLG_TIF_MASK);
|
||||
|
||||
return bflag;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除PIT通道中断标志位.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelClrFlags(uint8_t u8Channel)
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].TFLG |= PIT_TFLG_TIF_MASK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
void PIT_Init(uint8_t u8Channel_No, PIT_ConfigType *pConfig);
|
||||
void PIT_SetLoadVal(uint8_t u8Channel, uint32_t u32loadvalue);
|
||||
void PIT_SetCallback(uint8_t u8Channel_No, PIT_CallbackType pfnCallback);
|
||||
void PIT_DeInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* PIT_H_ */
|
||||
@@ -0,0 +1,137 @@
|
||||
/************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file rtc.c
|
||||
* @brief rtc定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
***************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "rtc.h"
|
||||
|
||||
/*!
|
||||
* @brief 存放中断回调入口
|
||||
*
|
||||
*/
|
||||
RTC_CallbackType RTC_Callback[1] = {(RTC_CallbackType)NULL};
|
||||
|
||||
|
||||
|
||||
void RTC_Isr(void);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 定义RTC的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化RTC模块
|
||||
*
|
||||
* @param[in] pConfig 配置RTC模块的结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_Init(RTC_ConfigType *pConfig)
|
||||
{
|
||||
uint16_t u16Clocksource, u16Prescler;
|
||||
uint16_t u16ModVal;
|
||||
|
||||
u16Clocksource =0;
|
||||
u16Prescler =0;
|
||||
u16ModVal =0;
|
||||
|
||||
SIM->SCGC |= SIM_SCGC_RTC_MASK;
|
||||
|
||||
u16ModVal = pConfig->u16ModuloValue;
|
||||
RTC_SetModulo(u16ModVal);
|
||||
|
||||
if (pConfig->bRTCOut)
|
||||
{
|
||||
RTC->SC= RTC_SC_RTCO_MASK;
|
||||
}
|
||||
|
||||
if (pConfig->bInterruptEn)
|
||||
{
|
||||
NVIC_EnableIRQ(RTC_IRQn);
|
||||
RTC_EnableInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
}
|
||||
|
||||
if (pConfig->bFlag)
|
||||
{
|
||||
RTC_ClrFlags();
|
||||
}
|
||||
|
||||
u16Clocksource = pConfig->bClockSource;
|
||||
u16Prescler = pConfig->bClockPresaler;
|
||||
|
||||
RTC_SetClock(u16Clocksource,u16Prescler );
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置RTC模块的中断回调函数
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_SetCallback(RTC_CallbackType pfnCallback)
|
||||
{
|
||||
RTC_Callback[0] = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位RTC模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_DeInit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
RTC->MOD = 0;
|
||||
while(RTC->MOD);
|
||||
|
||||
if(RTC_GetFlags())
|
||||
{
|
||||
RTC_ClrFlags();
|
||||
}
|
||||
|
||||
RTC->SC = 0;
|
||||
while(RTC->SC);
|
||||
SIM->SCGC &= ~SIM_SCGC_RTC_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC中断服务函数
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_Isr(void)
|
||||
{
|
||||
RTC_ClrFlags(); //清除中断标志位
|
||||
if (RTC_Callback[0])
|
||||
{
|
||||
RTC_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief RTC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef RTC_H_
|
||||
#define RTC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* RTC控制位定义
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
|
||||
#define RTC_OUTPUT_ENABLE 1 /*!< 使能RTC输出引脚 */
|
||||
#define RTC_INTERRUPT_ENABLE 1 /*!< 使能RTC中断 */
|
||||
#define RTC_CLKSRC_EXTERNAL 0 /*!< 选择外部时钟作为RTC时钟源 */
|
||||
#define RTC_CLKSRC_1KHZ 1 /*!< 选择LPO时钟作为RTC时钟源 */
|
||||
#define RTC_CLKSRC_IREF 2 /*!< 选择内部参考时钟ICSIRCLK作为RTC时钟源 */
|
||||
#define RTC_CLKSRC_BUS 3 /*!< 选择总线时钟作为RTC时钟源 */
|
||||
#define RTC_CLK_PRESCALER_128 1 /*!< 根据RTCLKS位选择是1还是128分频 */
|
||||
#define RTC_CLK_PRESCALER_256 2 /*!< 根据RTCLKS位选择是2还是256分频 */
|
||||
#define RTC_CLK_PRESCALER_512 3 /*!< 根据RTCLKS位选择是4还是512分频 */
|
||||
#define RTC_CLK_PRESCALER_1024 4 /*!< 根据RTCLKS位选择是8还是1024分频 */
|
||||
#define RTC_CLK_PRESCALER_2048 5 /*!< 根据RTCLKS位选择是16还是2048分频 */
|
||||
#define RTC_CLK_PRESCALER_100 6 /*!< 根据RTCLKS位选择是32还是100分频 */
|
||||
#define RTC_CLK_PRESCALER_1000 7 /*!< 根据RTCLKS位选择是64还是1000分频 */
|
||||
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @brief RTC 回调类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef void (*RTC_CallbackType)(void);
|
||||
|
||||
|
||||
|
||||
/* RTC 配置结构体体
|
||||
*/
|
||||
/*!
|
||||
* @brief RTC 配置参数.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bReserved : 4; /*!< 保留 */
|
||||
uint16_t bRTCOut : 1; /*!< 1: 使能RTC输出, 0: 禁止RTC输出 */
|
||||
uint16_t bReserved1 : 1; /*!< 保留 */
|
||||
uint16_t bInterruptEn : 1; /*!< 1: 使能RTC中断, 0: RTC 禁止RTC中断 */
|
||||
uint16_t bFlag : 1; /*!< 1: RTC实时中断标志 */
|
||||
uint16_t bClockPresaler : 3; /*!< 3: RTC分频系数选择 */
|
||||
uint16_t bReserved2 : 3; /*!< 保留*/
|
||||
uint16_t bClockSource : 2; /*!< 2:RTC时钟源选择 */
|
||||
uint16_t u16ModuloValue ; /*!< 16位RTC模值 */
|
||||
} RTC_ConfigType, *RTC_ConfigPtr;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能RTC中断.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_EnableInt(void)
|
||||
{
|
||||
RTC->SC |= RTC_SC_RTIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁止RTC中断.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return non
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_DisableInt(void)
|
||||
{
|
||||
RTC->SC &= ~RTC_SC_RTIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置16位RTC模值.
|
||||
*
|
||||
* @param[in] u16Mod_Value 16位模值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_SetModulo(uint16_t u16Mod_Value)
|
||||
{
|
||||
|
||||
RTC->MOD = u16Mod_Value;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置RTC时钟以及分频系数.
|
||||
*
|
||||
* @param[in] u16Clock_Number 选择时钟源
|
||||
* @param[in] u16Presalcer 分频系数
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_SetClock(uint16_t u16Clock_Number, uint16_t u16Presalcer)
|
||||
{
|
||||
uint32_t u32rtc_sc;
|
||||
|
||||
u32rtc_sc = RTC->SC;
|
||||
u32rtc_sc &= ~(RTC_SC_RTCLKS_MASK | RTC_SC_RTCPS_MASK);
|
||||
u32rtc_sc |= RTC_SC_RTCLKS(u16Clock_Number) | RTC_SC_RTCPS(u16Presalcer);
|
||||
RTC->SC = u32rtc_sc;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取RTC中断标志位.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return RTC中断标志位.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t RTC_GetFlags(void)
|
||||
{
|
||||
uint8_t bflag;
|
||||
|
||||
bflag = RTC->SC & RTC_SC_RTIF_MASK;
|
||||
|
||||
return bflag;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除RTC中断标志位.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_ClrFlags(void)
|
||||
{
|
||||
RTC->SC |= RTC_SC_RTIF_MASK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
void RTC_Init(RTC_ConfigType *pConfig);
|
||||
void RTC_SetCallback(RTC_CallbackType pfnCallback);
|
||||
void RTC_DeInit(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* RTC_H_ */
|
||||
@@ -0,0 +1,164 @@
|
||||
/*************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file sim.c
|
||||
* @brief 系统集成模块(SIM)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
*************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "sim.h"
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @ 初始化SIM寄存器.
|
||||
*
|
||||
* @ 输入 pConfig 指向SIM配置结构体.
|
||||
*
|
||||
* @ 无返回
|
||||
*
|
||||
* @ 参看 SIM_ConfigType
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SIM_Init(SIM_ConfigType *pConfig)
|
||||
{
|
||||
uint32_t u32Sopt;
|
||||
uint32_t u32PinSel;
|
||||
uint32_t u32Scgc;
|
||||
uint32_t u32BusDiv;
|
||||
/*
|
||||
* 初始化SIM寄存器
|
||||
*/
|
||||
u32Sopt = 0x0010000E; /*使能SWD、RESET、NMI引脚 */
|
||||
u32PinSel = 0;
|
||||
u32Scgc = 0x00003000; /* 使能SWD、FLASH模块的总线时钟 */
|
||||
u32BusDiv = 0;
|
||||
u32BusDiv = pConfig->sBits.bBusDiv; /*总线时钟分频值*/
|
||||
if(pConfig->sBits.bDisableNMI) /*禁用NMI引脚*/
|
||||
{
|
||||
u32Sopt &= ~SIM_SOPT_NMIE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bDisableRESET) /*禁用RSTPE引脚*/
|
||||
{
|
||||
u32Sopt &= ~SIM_SOPT_RSTPE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bDisableSWD) /*禁用SWDE引脚*/
|
||||
{
|
||||
u32Sopt &= ~SIM_SOPT_SWDE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bEnableCLKOUT) /*使能总线时钟*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_CLKOE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bETMSYNC) /*ETM2同步选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_ETMSYNC_MASK; /*生成ETM2模块的PWM同步触发*/
|
||||
}
|
||||
if(pConfig->sBits.bRXDCE) /*UAT0_RX捕捉选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_RXDCE_MASK; /*UAT0_RX输入信号接到UART0模块和ETM0通道1*/
|
||||
}
|
||||
if(pConfig->sBits.bTXDME) /*URAT0_TX捕捉选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_TXDME_MASK; /*URAT0_TX输出映射到引出线前由ETM0通道调制*/
|
||||
}
|
||||
if(pConfig->sBits.bACIC) /*模拟比较器至输入捕获使能*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_ACIC_MASK; /* ACMP0输出连接到ETM1输出通道0*/
|
||||
}
|
||||
if(pConfig->sBits.bRTCC)
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_RTCC_MASK; /*RTC溢出连接到ETM1输入通道*/
|
||||
}
|
||||
if(pConfig->sBits.bRXDFE) /*URT0 RxD滤波器选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_RXDFE_MASK; /*RXD0输入信号由ACMP0滤波,然后注入UART0*/
|
||||
}
|
||||
u32Sopt |= ((pConfig->u8BusRef & 0x07) << 16); /*总线时钟128分频*/
|
||||
u32Sopt |= ((pConfig->u8Delay) << 24); /*设置从ETM2初始化/匹配到触发ADC转换的延时时间*/
|
||||
u32Sopt |= ((pConfig->sBits.u8ADHWT & 0x03) << 8); /*选择ETM2匹配作为ADC转换的硬件触发源*/
|
||||
u32PinSel = pConfig->u32PinSel;
|
||||
u32Scgc = pConfig->u32SCGC;
|
||||
|
||||
/*写数据到SIM模块寄存器 */
|
||||
SIM->SOPT = u32Sopt;
|
||||
SIM->PINSEL = u32PinSel;
|
||||
SIM->SCGC = u32Scgc;
|
||||
SIM->BUSDIV = u32BusDiv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************//*!
|
||||
*
|
||||
* @ 设置SIM时钟选通控制寄存器,使能或者禁用外设门控时钟
|
||||
*
|
||||
* @ 输入 u32PeripheralMask 外设时钟掩码
|
||||
* @ 输入 u8GateOn 1:开启, 0:关闭.
|
||||
*
|
||||
* @ 无返回
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void SIM_SetClockGating(uint32_t u32PeripheralMask, uint8_t u8GateOn)
|
||||
{
|
||||
uint32_t u32Scgc;
|
||||
|
||||
u32Scgc = SIM->SCGC;
|
||||
|
||||
if(u8GateOn)
|
||||
{
|
||||
u32Scgc |= u32PeripheralMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32Scgc &= ~u32PeripheralMask;
|
||||
}
|
||||
|
||||
SIM->SCGC = u32Scgc;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @ 读取相应的状态标志位.
|
||||
*
|
||||
* @ 输入 u32StatusMask 指示要被读取的状态
|
||||
*
|
||||
* @ 返回状态.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint32_t SIM_GetStatus(uint32_t u32StatusMask)
|
||||
{
|
||||
uint32_t u32Status;
|
||||
|
||||
u32Status = SIM->SRSID & u32StatusMask; //读取状态标志位
|
||||
|
||||
return (u32Status);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @ 读相应的ID寄存器.
|
||||
*
|
||||
* @ 输入 u8ID ID的类型.
|
||||
*
|
||||
* @ 返回 ID
|
||||
*
|
||||
* 参看 IDType
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t SIM_ReadID(IDType sID)
|
||||
{
|
||||
uint32_t u32ID;
|
||||
uint8_t u8IDOffset[4] =
|
||||
{
|
||||
28, 24, 20,16
|
||||
};
|
||||
u32ID = (SIM->SRSID >> u8IDOffset[sID]) & 0x0F; //读取ID
|
||||
return (u32ID);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief SIM 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef SIM_H_
|
||||
#define SIM_H_
|
||||
|
||||
typedef enum {
|
||||
ID_TYPE_FAMID, /*!< NV32F100x系列 ID */
|
||||
ID_TYPE_SUBFAMID, /*!< NV32F100x子系列 ID */
|
||||
ID_TYPE_REVID, /*!< 器件版本 ID */
|
||||
ID_TYPE_PINID /*!< 器件引脚 ID */
|
||||
} IDType;
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
typedef struct{
|
||||
struct{
|
||||
uint32_t bEnableCLKOUT : 1; /*!< 1: 使能 , 0: 禁用 */
|
||||
uint32_t bTXDME : 1; /*!< 1: 使能 TXDME, 0: 禁用 */
|
||||
uint32_t bETMSYNC : 1; /*!< 1: 使能 ETM SYNC, 0: 未触发任何同步 */
|
||||
uint32_t bRXDFE : 1; /*!< 1: 使能 RXD 滤波, 0: 无滤波 */
|
||||
uint32_t bRXDCE : 1; /*!< 1: 使能 RXD 捕捉, 0: 无捕捉 */
|
||||
uint32_t bACIC : 1; /*!< 1: ACMP0的输出通道连接到ETM1的输入通道0, 0: 无连接 */
|
||||
uint32_t bRTCC : 1; /*!< 1: RTC溢出连接到ETM1输入通道1, 0: 无连接 */
|
||||
uint32_t u8ADHWT : 2; /*!< 选择ADC转换硬件触发源 */
|
||||
uint32_t bDisableSWD : 1; /*!< 1: 禁用SWD, 0: 使能 */
|
||||
uint32_t bDisableRESET : 1; /*!< 1: 禁用复位引脚, 0: 使能 */
|
||||
uint32_t bDisableNMI : 1; /*!< 1: 禁用NMI中断输入引脚, 0:使能 */
|
||||
uint32_t bBusDiv : 1; /*!< 总线分频系数 */
|
||||
} sBits;
|
||||
uint8_t u8Delay; /*!< ETM触发ADC转换延时值 */
|
||||
uint8_t u8BusRef; /*!< 总线参考 */
|
||||
uint32_t u32PinSel; /*!< 引脚选择寄存器的值*/
|
||||
uint32_t u32SCGC; /*!< 时钟选通寄存器的值 */
|
||||
} SIM_ConfigType, *SIM_ConfigPtr; /*!< SIM模块配置结构体类型 */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM2触发ADC转换的延时时间
|
||||
*
|
||||
* @param[in] u8Delay 延时时间模数值,参考时钟采用总线时钟分频
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DelayETM2Trig2ADC(uint8_t u8Delay)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_DELAY_MASK)) | SIM_SOPT_DELAY(u8Delay);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能总线时钟在PH2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ 参看 SIM_DisableClockOutput
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableClockOutput(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_CLKOE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用总线时钟输出在PH2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @参看 SIM_EnableClockOutput
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableClockOutput(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_CLKOE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置总线时钟输出分频.
|
||||
*
|
||||
* @param[in] u8Divide 分频系数 (3-bits)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_SetClockOutputDivide(uint8_t u8Divide)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_BUSREF_MASK)) | SIM_SOPT_BUSREF(u8Divide & 0x07);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_RX输入信号连接到UART0模块和ETM0通道1
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableUART0RXDConnectETMOCH1(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_RXDCE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_TX输出在映射到引出线前由ETM0通道0调制
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableUART0Modulation(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_TXDME_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_TX输出直接连接到引出线上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableUART0Modulation(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_TXDME_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成ETM2模块的PWM同步触发
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_GenerateSoftwareTrig2ETM2(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_ETMSYNC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH3通道映射到PD1上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH3Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS3_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH2通道映射到PD0上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH2Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS2_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM0_CH1通道映射到PB3上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM0CH1Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM0PS1_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM0_CH0通道映射到PB2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM0CH0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM0PS0_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_RX和UART0_TX映射到PA2和PA3上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapUART0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_UART0PS_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI0_SCK SPI0_MOSI SPI0_MISO和SPI0_PCS映射到PE0、PE1、PE2、PE3上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapSPI0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_SPI0PS_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief I2C0_SCL和I2C_SDA分别映射到PB7、PB6上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapI2CPin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_IICPS_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RXD0输入信号由ACPM0滤波,然后注入UART0
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableUART0Filter(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_RXDFE_MASK);
|
||||
}
|
||||
/******************************************************************************!
|
||||
*
|
||||
* @brief RXD0输入信号直接连接到UARTO模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableUART0Filter(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_RXDFE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择RTC溢出作为ADC硬件触发源
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByRTC(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_ADHWT_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择PIT溢出作为ADC硬件触发源
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByPIT(void)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_ADHWT_MASK)) | SIM_SOPT_ADHWT(1);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM2初始化作为ADC硬件触发源.ETM2初始化后经过一段时间延时触发ADC转换
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByETM2Init(void)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_ADHWT_MASK)) | SIM_SOPT_ADHWT(2);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM2匹配作为ADC硬件触发源,ETM2匹配后经过一段时间的延时触发ADC转换
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByETM2Match(void)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_ADHWT_MASK)) | SIM_SOPT_ADHWT(3);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC溢出连接到ETM1输入通道1
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableRTCCapture(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_RTCC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC溢出未连接到ETM1输入通道1
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableRTCCapture(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_RTCC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP0输出连接到ETM1输入通道0
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableACMP0InputCapture(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_ACIC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP0输出未连接到ETM1输入通道0
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableACMP0InputCapture(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_ACIC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC0映射到PC5上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapRTCPin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_RTCPS_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置总线时钟频率
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_SetBusDivide(uint8_t u8Divide)
|
||||
{
|
||||
SIM->BUSDIV = u8Divide;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH1通道映射到PH1上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH1Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS1_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH0通道映射到PH0上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS0_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM1_CH1通道映射到PE7上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM1CH1Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM1PS1_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM1_CH0映射到PH2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM1CH0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM1PS0_MASK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void SIM_Init(SIM_ConfigType *pConfig);
|
||||
void SIM_SetClockGating(uint32_t u32PeripheralMask, uint8_t u8GateOn);
|
||||
uint32_t SIM_GetStatus(uint32_t u32StatusMask);
|
||||
uint8_t SIM_ReadID(IDType sID);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file spi.c
|
||||
* @brief 串行外设接口模块(SPI)函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "spi.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放SPI回调函数接口
|
||||
****************************************************************************/
|
||||
|
||||
SPI_CallbackType SPI_Callback[MAX_SPI_NO] = {(SPI_CallbackType)NULL};
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化SPI模块
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块.
|
||||
* @param[in] pConfig 指向SPI配置参数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_Init(SPI_Type *pSPI, SPI_ConfigType *pConfig)
|
||||
{
|
||||
#if defined(CPU_NV32M3)
|
||||
/* sanity check */
|
||||
ASSERT((pSPI == SPI0));
|
||||
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
|
||||
#else
|
||||
/* sanity check */
|
||||
ASSERT((pSPI == SPI0) || (pSPI == SPI1));
|
||||
|
||||
/*使能SPI模块总线时钟*/
|
||||
if( pSPI == SPI0)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_SPI1_MASK;
|
||||
}
|
||||
#endif
|
||||
/*配置SPI控制寄存器 */
|
||||
if( pConfig->sSettings.bIntEn) //使能SPI中断
|
||||
{
|
||||
SPI_IntEnable(pSPI);
|
||||
#if defined(CPU_NV32M3)
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
#else
|
||||
if( pSPI == SPI0 )
|
||||
{
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(SPI1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bTxIntEn) //使能SPI发送中断
|
||||
{
|
||||
SPI_TxIntEnable(pSPI);
|
||||
#if defined(CPU_NV32M3)
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
#else
|
||||
if( pSPI == SPI0 )
|
||||
{
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(SPI1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if( pConfig->sSettings.bMasterMode) //主/从机选择
|
||||
{
|
||||
SPI_SetMasterMode(pSPI); //SPI设置为主机模式
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_SetSlaveMode(pSPI); //SPI设置为从机模式
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bClkPolarityLow) //时钟极性配置
|
||||
{
|
||||
SPI_SetClockPol(pSPI,1);
|
||||
}
|
||||
if( pConfig->sSettings.bClkPhase1) //时钟相位配置
|
||||
{
|
||||
SPI_SetClockPhase(pSPI,1);
|
||||
}
|
||||
if( pConfig->sSettings.bShiftLSBFirst) //设置SPI串行数据传输开始位
|
||||
{
|
||||
SPI_SetLSBFirst(pSPI); // SPI串行数据传输从最低位开始(LSB)
|
||||
}
|
||||
if( pConfig->sSettings.bMatchIntEn)
|
||||
{
|
||||
SPI_MatchIntEnable(pSPI); //使能SPI匹配中断
|
||||
}
|
||||
if( pConfig->sSettings.bModeFaultEn)
|
||||
{
|
||||
SPI_ModfEnable(pSPI); //使能主机模式模式错误功能.
|
||||
}
|
||||
if( pConfig->sSettings.bMasterAutoDriveSS)
|
||||
{
|
||||
/*设置SSOE和MODFEN位,从机模式中SS引脚为从机输出,自动驱动从机SS引脚使能*/
|
||||
SPI_SSOutputEnable(pSPI);
|
||||
SPI_ModfEnable(pSPI);
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bPinAsOuput)
|
||||
{
|
||||
SPI_BidirPinEnable(pSPI); //使能双向引脚配置.
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bBidirectionModeEn)
|
||||
{
|
||||
SPI_BidirOutEnable(pSPI); //使能双向模式输出.
|
||||
}
|
||||
if( pConfig->sSettings.bStopInWaitMode)
|
||||
{
|
||||
SPI_ClockStopEnable(pSPI); //SPI时钟在等待模式下关闭
|
||||
}
|
||||
|
||||
if(pConfig->sSettings.bMasterMode) //设置波特率
|
||||
{
|
||||
SPI_SetBaudRate(pSPI,pConfig->u32BusClkHz,pConfig->u32BitRate);
|
||||
}
|
||||
|
||||
/*使能SPI模块*/
|
||||
if( pConfig->sSettings.bModuleEn)
|
||||
{
|
||||
SPI_Enable(pSPI);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI波特率.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u32BusClock 总线时钟.
|
||||
* @param[in] u32Bps SPI波特率.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_SetBaudRate(SPI_Type *pSPI,uint32_t u32BusClock,uint32_t u32Bps)
|
||||
{
|
||||
uint32_t u32BitRateDivisor;
|
||||
uint8_t u8Sppr;
|
||||
uint8_t u8Spr;
|
||||
uint8_t u8ReadFlag;
|
||||
u32BitRateDivisor = u32BusClock/u32Bps; /* 计算波特率因子 */
|
||||
|
||||
u8ReadFlag = 0;
|
||||
/* 计算最适合的 SPPR 和 SPR */
|
||||
for (u8Spr = 0; u8Spr <= 8; u8Spr++)
|
||||
{
|
||||
for(u8Sppr = 0; u8Sppr <= 7; u8Sppr++)
|
||||
{
|
||||
if((u32BitRateDivisor>>(u8Spr+1))<=(u8Sppr+1))
|
||||
{
|
||||
u8ReadFlag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(u8ReadFlag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(u8Sppr >=8)
|
||||
{
|
||||
u8Sppr = 7;
|
||||
}
|
||||
if(u8Spr >8)
|
||||
{
|
||||
u8Spr = 8;
|
||||
}
|
||||
/* 设置波特率 */
|
||||
pSPI->BR = SPI_BR_SPPR(u8Sppr) | SPI_BR_SPR(u8Spr);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读/写数据寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块.
|
||||
* @param[in] pWrBuff -- 发送(写)数组指针
|
||||
* @param[in] uiLength -- 读/写数据长度.
|
||||
* @param[out] pRdBuff -- 接收(读)数组指针.
|
||||
*
|
||||
* @return if <0, means error, 0: success.
|
||||
*
|
||||
*****************************************************************************/
|
||||
ResultType SPI_TransferWait(SPI_Type *pSPI, SPI_WidthType* pRdBuff, SPI_WidthType *pWrBuff,uint32 uiLength)
|
||||
{
|
||||
ResultType err = SPI_ERR_SUCCESS;
|
||||
uint32_t i;
|
||||
|
||||
if(!uiLength)
|
||||
{
|
||||
return (err);
|
||||
}
|
||||
for(i = 0; i < uiLength; i++)
|
||||
{
|
||||
while(!SPI_IsSPTEF(pSPI));
|
||||
SPI_WriteDataReg(pSPI,pWrBuff[i]);
|
||||
while(!SPI_IsSPRF(pSPI));
|
||||
pRdBuff[i] = SPI_ReadDataReg(pSPI);
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位SPI模块
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_DeInit(SPI_Type *pSPI)
|
||||
{
|
||||
int16 i;
|
||||
pSPI->C1 = SPI_C1_DEFAULT;
|
||||
pSPI->C2 = SPI_C2_DEFAULT;
|
||||
pSPI->BR = SPI_BR_DEFAULT;
|
||||
pSPI->M = SPI_M_DEFAULT;
|
||||
for(i = 0; i<100; i++); /*延时一段时间,等待SPI退出中断 */
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI回调函数,在中断服务函数中调用
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] pfnCallback 回调函数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_SetCallback(SPI_Type *pSPI,SPI_CallbackType pfnCallback)
|
||||
{
|
||||
uint32_t u32Port = ((uint32_t)pSPI-(uint32_t)SPI0)>>12;
|
||||
ASSERT(u32Port <2);
|
||||
SPI_Callback[u32Port] = pfnCallback;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI0 中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void SPI0_Isr(void)
|
||||
{
|
||||
if( SPI_Callback[0] )
|
||||
{
|
||||
SPI_Callback[0]();
|
||||
}
|
||||
}
|
||||
#ifndef CPU_NV32M3
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI1 中断服务函数
|
||||
*
|
||||
* @param none.
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void SPI1_Isr(void)
|
||||
{
|
||||
if( SPI_Callback[1] )
|
||||
{
|
||||
SPI_Callback[1]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,567 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief SPI 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef SPI_H_
|
||||
#define SPI_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* 定义SPI模块个数
|
||||
******************************************************************************/
|
||||
#define MAX_SPI_NO 2
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义SPI寄存复位值
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define SPI_C1_DEFAULT 0x04 /*!< SPI 控制寄存器1 */
|
||||
#define SPI_C2_DEFAULT 0x00 /*!< SPI 控制寄存器2 */
|
||||
#define SPI_BR_DEFAULT 0x00 /*!< SPI 波特率寄存器 */
|
||||
#define SPI_S_DEFAULT 0x20 /*!< SPI 状态寄存器 */
|
||||
#define SPI_M_DEFAULT 0x00 /*!< SPI 匹配寄存器 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义SPI传输状态
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define SPI_ERR_SUCCESS 0 /*!< 成功 */
|
||||
#define SPI_ERR_CODE_BASE ((uint32)SPI0 - 0x40000000L) /*!< SPI基地址错误 */
|
||||
#define SPI_ERR_TXBUF_NOT_EMPTY (SPI_ERR_CODE_BASE+1) /*!< 失败由于发送缓冲区空时,标志位没有置位*/
|
||||
#define SPI_ERR_RXBUF_NOT_FULL (SPI_ERR_CODE_BASE+2) /*!< 失败由于接收缓冲区满时,标志位没有置位 */
|
||||
|
||||
/******************************************************************************
|
||||
* 数据类型别名定义
|
||||
******************************************************************************/
|
||||
|
||||
typedef uint8_t SPI_WidthType; /* SPI 发送数据宽度类型 */
|
||||
typedef uint32_t ResultType; /* SPI 收发返回状态数据类型 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SPI回调函数声明
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef void (*SPI_CallbackType)(void);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SPI 结构体类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bIntEn : 1; /*!< 1: 使能中断, 0: 禁用中断*/
|
||||
uint32_t bModuleEn : 1; /*!< 1: 使能SPI模块, 0: 禁用SPI模块 */
|
||||
uint32_t bTxIntEn : 1; /*!< 1: 使能发送中断, 0: 禁用发送中断 */
|
||||
uint32_t bMasterMode : 1; /*!< 1: 主机模式, 0: 从机模式 */
|
||||
uint32_t bClkPolarityLow : 1; /*!< 设置时钟极性 */
|
||||
uint32_t bClkPhase1 : 1; /*!< 设置时钟相位 */
|
||||
uint32_t bMasterAutoDriveSS : 1; /*!< 从机选择输出使能 */
|
||||
uint32_t bShiftLSBFirst : 1; /*!< 1: LSB, 0: MSB */
|
||||
uint32_t bMatchIntEn : 1; /*!< 1: 使能匹配中断, 0: 禁用匹配中断 */
|
||||
uint32_t bModeFaultEn : 1; /*!< 使能主机模式错误功能 */
|
||||
uint32_t bBidirectionModeEn : 1; /*!< 双向模式输出控制 */
|
||||
uint32_t bPinAsOuput : 1; /*!< SPI引脚控制 */
|
||||
uint32_t bStopInWaitMode : 1; /*!< 配置SPI时钟在等待模式下的工作状态 */
|
||||
uint32_t bRsvd : 19;
|
||||
} SPI_SettingType;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SPI配置结构体类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SPI_SettingType sSettings; /*!< SPI 结构体 */
|
||||
uint32_t u32BitRate; /*!< 设置波特率 */
|
||||
uint32_t u32BusClkHz; /*!< 输入总线时钟 */
|
||||
} SPI_ConfigType; /*!< SPI配置结构体 */
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI串行数据传输从最低位开始(LSB)
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetLSBFirst(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_LSBFE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI串行数据传输从最高位开始(MSB)
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetMSBFirst(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_LSBFE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI时钟极性.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
* @param[in] u8PolLow 设置时钟极性. 1-SCK时钟有效状态为高(无效状态为低)
|
||||
* 0-SCK时钟有效状态为低(无效状态为高)
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetClockPol(SPI_Type *pSPI,uint8_t u8PolLow)
|
||||
{
|
||||
if( u8PolLow )
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_CPOL_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_CPOL_MASK;
|
||||
}
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI时钟相位.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u8Phase 设置时钟相位, 1 - 数据在SCK下降沿输出,在上升沿采样.
|
||||
* 0 - 数据在SCK上升沿采样,在下降沿输出
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetClockPhase(SPI_Type *pSPI,uint8_t u8Phase)
|
||||
{
|
||||
if( u8Phase )
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_CPHA_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_CPHA_MASK;
|
||||
}
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI模块.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_Enable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SPE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI模块
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_Disable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SPE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_IntEnable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SPIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_IntDisable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SPIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI为主机模式.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SetMasterMode(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_MSTR_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI为从机模式.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SetSlaveMode(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_MSTR_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI发送中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_TxIntEnable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SPTIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI发送中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_TxIntDisable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SPTIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能从机选择输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SSOutputEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SSOE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用从机选择输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SSOutputDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SSOE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI匹配中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_MatchIntEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_SPMIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI匹配中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_MatchIntDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_SPMIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用主机模式错误功能
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ModfDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_MODFEN_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
|
||||
*
|
||||
* @brief 使能主机模式模式错误功能.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ModfEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_MODFEN_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能双向模式输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirOutEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_BIDIROE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用双向模式输出
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirOutDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_BIDIROE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI时钟在等待模式下一直运行
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ClockStopDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_SPISWAI_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI时钟在等待模式下关闭
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ClockStopEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_SPISWAI_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能双向引脚配置.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirPinEnable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_SPC0_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI使用独立的引脚用作数据的输入输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirPinDisable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_SPC0_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取接收数据缓冲区满标准位.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsSPRF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_SPRF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取SPI匹配标志位
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsSPMF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_SPMF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取SPI发送数据缓冲区空标志位.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsSPTEF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_SPTEF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取主机模式错误标志位
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsMODF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_MODF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取SPI数据寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return 数据寄存器的值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_ReadDataReg(SPI_Type *pSPI )
|
||||
{
|
||||
return pSPI->D;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写数据到SPI数据寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u8WrBuff 写到SPI数据寄存器的数据缓冲区
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_WriteDataReg(SPI_Type *pSPI, uint8_t u8WrBuff )
|
||||
{
|
||||
pSPI->D = u8WrBuff;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写数据到SPI匹配寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u8WrBuff 写到SPI匹配寄存器的数据缓冲区
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_WriteMatchValue(SPI_Type *pSPI, uint8_t u8WrBuff )
|
||||
{
|
||||
pSPI->M = u8WrBuff;
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
||||
void SPI_Enable(SPI_Type *pSPI);
|
||||
void SPI_Disable(SPI_Type *pSPI);
|
||||
void SPI_SetLSBFirst(SPI_Type *pSPI);
|
||||
void SPI_SetMSBFirst(SPI_Type *pSPI);
|
||||
void SPI_IntEnable(SPI_Type *pSPI);
|
||||
void SPI_IntDisable(SPI_Type *pSPI);
|
||||
void SPI_SetMasterMode(SPI_Type *pSPI);
|
||||
void SPI_SetSlaveMode(SPI_Type *pSPI);
|
||||
void SPI_TxIntEnable(SPI_Type *pSPI);
|
||||
void SPI_TxIntDisable(SPI_Type *pSPI);
|
||||
void SPI_SSOutputEnable(SPI_Type *pSPI );
|
||||
void SPI_SSOutputDisable(SPI_Type *pSPI );
|
||||
void SPI_MatchIntEnable(SPI_Type *pSPI );
|
||||
void SPI_MatchIntDisable(SPI_Type *pSPI );
|
||||
void SPI_ModfDisable(SPI_Type *pSPI );
|
||||
void SPI_ModfEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirOutEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirOutDisable(SPI_Type *pSPI );
|
||||
void SPI_ClockStopDisable(SPI_Type *pSPI );
|
||||
void SPI_ClockStopEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirPinEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirPinDisable(SPI_Type *pSPI );
|
||||
void SPI_SetClockPol(SPI_Type *pSPI,uint8_t u8PolLow);
|
||||
void SPI_SetClockPhase(SPI_Type *pSPI,uint8_t u8Phase);
|
||||
void SPI_SetBaudRate(SPI_Type *pSPI,uint32_t u32BusClock,uint32_t u32Bps );
|
||||
uint8_t SPI_IsSPRF(SPI_Type *pSPI );
|
||||
uint8_t SPI_IsSPMF(SPI_Type *pSPI );
|
||||
uint8_t SPI_IsSPTEF(SPI_Type *pSPI );
|
||||
uint8_t SPI_IsMODF(SPI_Type *pSPI );
|
||||
uint8_t SPI_ReadDataReg(SPI_Type *pSPI );
|
||||
void SPI_WriteDataReg(SPI_Type *pSPI, uint8_t u8WrBuff );
|
||||
void SPI_WriteMatchValue(SPI_Type *pSPI, uint8_t u8WrBuff );
|
||||
void SPI_Init(SPI_Type *pSPI, SPI_ConfigType *pConfig);
|
||||
void SPI_DeInit(SPI_Type *pSPI);
|
||||
ResultType SPI_TransferWait(SPI_Type *pSPI, SPI_WidthType* pRdBuff, SPI_WidthType *pWrBuff,uint32 uiLength);
|
||||
void SPI_SetCallback(SPI_Type *pSPI,SPI_CallbackType pfnCallback);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,437 @@
|
||||
/*************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file uart.c
|
||||
* @brief uart通讯接口函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
*************************************************************************/
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
UART_CallbackType UART_Callback = NULL;
|
||||
|
||||
/******************************************************************************
|
||||
* 定义UART的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化UART,关中断,无硬件流控制.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pConfig 配置UART的结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_Init(UART_Type *pUART, UART_ConfigType *pConfig)
|
||||
{
|
||||
uint16_t u16Sbr;
|
||||
uint8_t u8Temp;
|
||||
uint32_t u32SysClk = pConfig->u32SysClkHz;//定义系统时钟
|
||||
uint32_t u32Baud = pConfig->u32Baudrate;//定义波特率
|
||||
|
||||
/* 合法性检查 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
/* 设置时钟选通控制用来选择相应的 UART 口 */
|
||||
if (pUART == UART0)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_UART0_MASK;//使能相应功能位, 选通对应 UART
|
||||
}
|
||||
#if defined(CPU_NV32)
|
||||
else if (pUART == UART1)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_UART1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_UART2_MASK;
|
||||
}
|
||||
#endif
|
||||
/*确保在我们进行配置时, 禁止发送和接收*/
|
||||
pUART->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
|
||||
|
||||
/* 配置 UART 为 8 位模式, 无奇偶校验位 */
|
||||
pUART->C1 = 0;
|
||||
|
||||
/* 波特率计算 */
|
||||
u16Sbr = (((u32SysClk)>>4) + (u32Baud>>1))/u32Baud;
|
||||
|
||||
/*把当前数据存放在串口波特率寄存器中, 且SBR位清0,即波特率发生器被禁止*/
|
||||
u8Temp = pUART->BDH & ~(UART_BDH_SBR_MASK);
|
||||
|
||||
pUART->BDH = u8Temp | UART_BDH_SBR(u16Sbr >> 8);
|
||||
pUART->BDL = (uint8_t)(u16Sbr & UART_BDL_SBR_MASK);
|
||||
|
||||
/*使能 UART 接收和发送 */
|
||||
pUART->C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK );
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 接收一个字符.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 接收到的字符
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t UART_GetChar(UART_Type *pUART)
|
||||
{
|
||||
|
||||
/* 合法性检测 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
/* 等待直到一个字符被接收 */
|
||||
while (!(pUART->S1 & UART_S1_RDRF_MASK));
|
||||
|
||||
/* 返回接收到的8位数据 */
|
||||
return pUART->D;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送一个字符.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] u8Char 要发送的字符
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_PutChar(UART_Type *pUART, uint8_t u8Char)
|
||||
{
|
||||
/* 一直等待, 直到缓冲区为空 */
|
||||
while (!(pUART->S1 & UART_S1_TDRE_MASK));
|
||||
|
||||
/* 发送字符到数据寄存器 */
|
||||
pUART->D = (uint8_t)u8Char;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 波特率设置.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pConfig 波特率相关配置结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_SetBaudrate(UART_Type *pUART, UART_ConfigBaudrateType *pConfig)
|
||||
{
|
||||
uint8_t u8Temp;
|
||||
uint16_t u16Sbr;
|
||||
uint32_t u32SysClk = pConfig->u32SysClkHz;
|
||||
uint32_t u32baud = pConfig->u32Baudrate;
|
||||
|
||||
/* 合法性检测 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
/*计算波特率,四舍五入提高精度 */
|
||||
u16Sbr = (((u32SysClk)>>4) + (u32baud>>1))/u32baud;
|
||||
|
||||
|
||||
u8Temp = pUART->BDH & ~(UART_BDH_SBR_MASK);
|
||||
|
||||
pUART->BDH = u8Temp | UART_BDH_SBR(u16Sbr >> 8);
|
||||
pUART->BDL = (uint8_t)(u16Sbr & UART_BDL_SBR_MASK);
|
||||
|
||||
|
||||
pUART->C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK );
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能UART中断.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] InterruptType 中断的类型
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_EnableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType)
|
||||
{
|
||||
|
||||
/* 通道合法性检查 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
if (InterruptType == UART_TxBuffEmptyInt) //发送中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_TIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_TxCompleteInt) //传输完成中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_TCIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_RxBuffFullInt) //接收器中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_RIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_IdleLineInt) //空闲线中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_ILIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_RxOverrunInt) //过载中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_ORIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_NoiseErrorInt) //噪声错误中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_NEIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_FramingErrorInt) //帧错误中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_FEIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_ParityErrorInt) //奇偶校验中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_FEIE_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
//其他暂不支持类型的中断
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用UART中断.
|
||||
*
|
||||
* @param[in] 指向三个UART其中一个的基址
|
||||
* @param[in] 中断的类型
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_DisableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType)
|
||||
{
|
||||
/* 通道合法性检查 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
|
||||
if (InterruptType == UART_TxBuffEmptyInt) //发送中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_TxCompleteInt) //传输完成中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TCIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_RxBuffFullInt) //接收器中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_RIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_IdleLineInt) //空闲线中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_ILIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_RxOverrunInt) //过载中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_ORIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_NoiseErrorInt) //噪声错误中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_NEIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_FramingErrorInt) //帧错误中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_FEIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_ParityErrorInt) //奇偶校验中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_FEIE_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
//其他暂不支持类型的中断
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 从两个状态寄存器获取UART状态
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 16位的状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint16_t UART_GetFlags(UART_Type *pUART)
|
||||
{
|
||||
uint16_t u16StatusFlags = 0;//先清空标志位
|
||||
|
||||
u16StatusFlags = pUART->S2; //将状态寄存器 2 的值赋给标志参数
|
||||
u16StatusFlags = (u16StatusFlags<<8)| pUART->S1; //两个状态寄存器拼接赋给标志参数
|
||||
|
||||
return u16StatusFlags;//返回标志参数的值
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查特定的位是否置位.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] FlagType 位的类型
|
||||
*
|
||||
* @return
|
||||
* 1, 标志置位
|
||||
* 0, 标志清零
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t UART_CheckFlag(UART_Type *pUART, UART_FlagType FlagType)
|
||||
{
|
||||
uint16_t u16StatusFlags = 0;
|
||||
|
||||
u16StatusFlags = UART_GetFlags(pUART);
|
||||
|
||||
return (u16StatusFlags & (1<<FlagType));
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用查询模式发送字符串.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pSendBuff 字符串首地址
|
||||
* @param[in] u32Length 字符串的长度
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_SendWait(UART_Type *pUART, uint8_t *pSendBuff, uint32_t u32Length)
|
||||
{
|
||||
uint8_t u8TxChar;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < u32Length; i++)
|
||||
{
|
||||
u8TxChar = pSendBuff[i];
|
||||
while (!UART_IsTxBuffEmpty(pUART))
|
||||
{
|
||||
#if defined(ENABLE_WDOG)
|
||||
WDOG_Feed();
|
||||
#endif
|
||||
}
|
||||
UART_WriteDataReg(pUART, u8TxChar);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用查询模式接收字符串.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pReceiveBuff 定义接收字符串的首地址
|
||||
* @param[in] u32Length 所要接收字符串的长度
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_ReceiveWait(UART_Type *pUART, uint8_t *pReceiveBuff, uint32_t u32Length)
|
||||
{
|
||||
uint8_t u8RxChar;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < u32Length; i++)
|
||||
{
|
||||
while (!UART_IsRxBuffFull(pUART))
|
||||
{
|
||||
#if defined(ENABLE_WDOG)
|
||||
WDOG_Feed();
|
||||
#endif
|
||||
}
|
||||
u8RxChar = UART_ReadDataReg(pUART);
|
||||
pReceiveBuff[i] = u8RxChar;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 等待发送完成.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_WaitTxComplete(UART_Type *pUART)
|
||||
{
|
||||
while (!UART_IsTxComplete(pUART));//一直等待直到发送完成
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置UART模块的中断回调函数.
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_SetCallback(UART_CallbackType pfnCallback)
|
||||
{
|
||||
UART_Callback = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief uart0 中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART0_Isr(void)
|
||||
{
|
||||
UART_Callback(UART0);
|
||||
}
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief uart0 中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART1_Isr(void)
|
||||
{
|
||||
UART_Callback(UART1);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief uart0 中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART2_Isr(void)
|
||||
{
|
||||
UART_Callback(UART2);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,461 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief UART 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "wdog.h"
|
||||
|
||||
#define MAX_UART_NO 3
|
||||
|
||||
|
||||
/*!
|
||||
* @brief UART 设置类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bEnable : 1; /*!< 1: 使能, 0: 禁用 */
|
||||
uint32_t resvd : 31; /*!< 1: 保留位域 */
|
||||
} UART_SettingType;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief UART 配置结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UART_SettingType sSettings; /*!< UART 设置 */
|
||||
uint32_t u32SysClkHz; /*!< 系统时钟 */
|
||||
uint32_t u32Baudrate; /*!< UART 波特率 */
|
||||
} UART_ConfigType;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief UART 波特率配置结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t u32SysClkHz; /*!< 系统时钟 */
|
||||
uint32_t u32Baudrate; /*!< UART 波特率 */
|
||||
} UART_ConfigBaudrateType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*define uart配置模式列表
|
||||
*
|
||||
*//*! @uart配置模式列表
|
||||
* @{
|
||||
******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
UART_Mode8Bit, /*!< 8位模式 */
|
||||
UART_Mode9Bit, /*!< 9位模式 */
|
||||
UART_ModeEnableLoopback, /*!< 使能环回模式 */
|
||||
UART_ModeDisableLoopback, /*!< 禁用环回模式*/
|
||||
UART_ModeEnableSingleWire, /*!< 使能UART单线模式 */
|
||||
UART_ModeDisableSingleWire, /*!< 禁用UART单线模式 */
|
||||
} UART_ModeType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*define uart中断类型
|
||||
*
|
||||
*//*! @uart中断类型列表
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UART_TxBuffEmptyInt, /*!< 发送中断 */
|
||||
UART_TxCompleteInt, /*!< 传输完成中断 */
|
||||
UART_RxBuffFullInt, /*!< 接收器中断 */
|
||||
|
||||
UART_IdleLineInt, /*!< 空闲线中断 */
|
||||
|
||||
UART_RxOverrunInt, /*!< 过载中断 */
|
||||
UART_NoiseErrorInt, /*!< 噪声错误中断 */
|
||||
UART_FramingErrorInt, /*!< /帧错误中断 */
|
||||
UART_ParityErrorInt, /*!< 奇偶校验中断 */
|
||||
} UART_InterruptType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*define uart标志类型定义
|
||||
*
|
||||
*//*! @uart标志类型定义列表
|
||||
* @{
|
||||
******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
UART_FlagPF = 0, /*!< 奇数 */
|
||||
UART_FlagFE, /*!< 帧错误标志 */
|
||||
UART_FlagNF, /*!< 噪声标志 */
|
||||
UART_FlagOR, /*!< 接收过载 */
|
||||
UART_FlagIDLE, /*!< 空闲线标志 */
|
||||
UART_FlagRDRF, /*!< 接收数据满标志 */
|
||||
UART_FlagTC, /*!< 发送完成标志 */
|
||||
UART_FlagTDRE, /*!< 发送寄存器空标志 */
|
||||
|
||||
UART_FlagRAF, /*!< 有效接收器标志 */
|
||||
UART_FlagLBKDE, /*!< LIN间隔检测使能 */
|
||||
UART_FlagBRK13, /*!< 间隔字符长度 */
|
||||
UART_FlagRWUID, /*!< 接收唤醒空闲检测 */
|
||||
UART_FlagRXINV, /*!< 接收数据反转 */
|
||||
UART_FlagRev1, /*!< 保留 */
|
||||
UART_FlagRXEDGIF, /*!< RXD引脚的有效边沿中断标志 */
|
||||
UART_FlagLBKDIF, /*!< LIN终止检测中断标志 */
|
||||
} UART_FlagType;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief UART 回调类型.
|
||||
*
|
||||
*/
|
||||
typedef void (*UART_CallbackType)(UART_Type *pUART);
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
/******************************************************************************
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取接收数据
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 接收到的字符
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_ReadDataReg(UART_Type *pUART)
|
||||
{
|
||||
return pUART->D;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写发送字符
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] u8Char 需要发送的字符
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_WriteDataReg(UART_Type *pUART, uint8_t u8Char)
|
||||
{
|
||||
pUART->D = (uint8_t)u8Char;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测接收数据寄存器是否满
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 0, 没有字符接收; 非0, 有字符接收到
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_CharPresent(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_RDRF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能发送器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableTx(UART_Type *pUART)
|
||||
{
|
||||
|
||||
pUART->C2 |= UART_C2_TE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用发送器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableTx(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能接收器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableRx(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_RE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用接收器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableRx(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_RE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能循环模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableLoopback(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 |= UART_C1_LOOPS_MASK;
|
||||
pUART->C1 &= (~UART_C1_RSRC_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能单线模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableSingleWire(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 |= UART_C1_LOOPS_MASK;
|
||||
pUART->C1 |= UART_C1_RSRC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置8位模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_Set8BitMode(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 &= (~UART_C1_M_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置9位模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_Set9BitMode(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 |= UART_C1_M_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能发送空中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableTxBuffEmptyInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_TIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能发送完成中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableTxCompleteInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_TCIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能接收满中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableRxBuffFullInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_RIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用发送空中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableTxBuffEmptyInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用传输完成中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableTxCompleteInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TCIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用接收满中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableRxBuffFullInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_RIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送间隔字符
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_PutBreak(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_SBK_MASK;
|
||||
pUART->C2 &= (~UART_C2_SBK_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测发送完成标志.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return
|
||||
* 1, 发送标志置位
|
||||
* 0, 发送标志清除
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_IsTxComplete(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_TC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测发送寄存器是否空
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return
|
||||
* 1, 发送寄存器空
|
||||
* 0, 发送寄存器不为空
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_IsTxBuffEmpty(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_TDRE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测接收数据寄存器是否满
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return
|
||||
* 1, 接收数据寄存器满
|
||||
* 0, 接收数据寄存器不为满
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_IsRxBuffFull(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_RDRF_MASK);
|
||||
}
|
||||
/*! @} */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
void UART_Init(UART_Type *pUART, UART_ConfigType *pConfig);
|
||||
uint8_t UART_GetChar(UART_Type *pUART);
|
||||
void UART_PutChar(UART_Type *pUART, uint8_t u8Char);
|
||||
void UART_SetBaudrate(UART_Type *pUART, UART_ConfigBaudrateType *pConfig);
|
||||
void UART_EnableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType);
|
||||
void UART_DisableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType);
|
||||
uint16_t UART_GetFlags(UART_Type *pUART);
|
||||
uint8_t UART_CheckFlag(UART_Type *pUART, UART_FlagType FlagType);
|
||||
void UART_SendWait(UART_Type *pUART, uint8_t *pSendBuff, uint32_t u32Length);
|
||||
void UART_ReceiveWait(UART_Type *pUART, uint8_t *pReceiveBuff, uint32_t u32Length);
|
||||
void UART_WaitTxComplete(UART_Type *pUART);
|
||||
void UART_SetCallback(UART_CallbackType pfnCallback);
|
||||
void UART0_Isr(void);
|
||||
void UART1_Isr(void);
|
||||
void UART2_Isr(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _UART_H_ */
|
||||
@@ -0,0 +1,265 @@
|
||||
/****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file wdg.c
|
||||
* @brief wdg定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
*******************************************************************************/
|
||||
#include "common.h"
|
||||
#include "wdog.h"
|
||||
|
||||
/******************************************************************************
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用看门狗定时器
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void WDOG_Disable(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 &= ~WDOG_CS1_EN_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用看门狗但允许其重新配置.
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_DisableWDOGEnableUpdate(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 &= ~WDOG_CS1_EN_MASK;
|
||||
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
|
||||
|
||||
|
||||
WDOG_Unlock(); //Modify
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能看门狗定时器.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_Enable(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
|
||||
u8Cs1 |= WDOG_CS1_EN_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化看门狗.
|
||||
*
|
||||
* @param[in] pConfig 配置看门狗的结构体.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @warning make sure that WDOG is not initialized after reset or WDOG update is enabled
|
||||
* after reset by calling WDOG_EnableUpdate / WDOG_DisableWDOGEnableUpdate.
|
||||
*
|
||||
* @see WDOG_EnableUpdate, WDOG_DisableWDOGEnableUpdate
|
||||
*
|
||||
*************************************************************************/
|
||||
void WDOG_Init(WDOG_ConfigPtr pConfig)
|
||||
{
|
||||
uint8_t u8Cs1;
|
||||
uint8_t u8Cs2;
|
||||
uint16_t u16Toval;
|
||||
uint16_t u16Win;
|
||||
|
||||
u8Cs1 = 0x80; /* CS1寄存器的默认值 */
|
||||
u8Cs2 = 0;
|
||||
u16Toval = pConfig->u16ETMeOut;
|
||||
u16Win = pConfig->u16WinETMe;
|
||||
|
||||
if(pConfig->sBits.bDisable)
|
||||
{
|
||||
u8Cs1 &= ~WDOG_CS1_EN_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bIntEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_INT_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bStopEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_STOP_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bDbgEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_DBG_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bWaitEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_WAIT_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bUpdateEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bWinEnable)
|
||||
{
|
||||
u8Cs2 |= WDOG_CS2_WIN_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bPrescaler)
|
||||
{
|
||||
u8Cs2 |= WDOG_CS2_PRES_MASK;
|
||||
}
|
||||
u8Cs2 |= (pConfig->sBits.bClkSrc & 0x03);
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
|
||||
WDOG->TOVAL8B.TOVALL = u16Toval;
|
||||
WDOG->TOVAL8B.TOVALH = u16Toval >> 8;
|
||||
|
||||
WDOG->WIN8B.WINL = u16Win;
|
||||
WDOG->WIN8B.WINH = u16Win >> 8;
|
||||
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_DeInit(void)
|
||||
{
|
||||
WDOG_Unlock();
|
||||
|
||||
WDOG->CS2 = WDOG_CS2_DEFAULT_VALUE;
|
||||
WDOG->TOVAL = WDOG_TOVAL_DEFAULT_VALUE;
|
||||
WDOG->WIN = WDOG_WIN_DEFAULT_VALUE;
|
||||
WDOG->CS1 = WDOG_CS1_DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 喂狗-刷新看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_Feed(void)
|
||||
{
|
||||
//在喂狗期间,总中断需要关闭
|
||||
DisableInterrupts;
|
||||
WDOG->CNT = 0x02A6;//喂狗的两条指令,必须跟随在128个总线时钟周期内执行
|
||||
WDOG->CNT = 0x80B4;
|
||||
EnableInterrupts;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能更新看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_EnableUpdate(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用更新看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_DisableUpdate(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 &= ~WDOG_CS1_UPDATE_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief WDG 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __WDOG_H__
|
||||
#define __WDOG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "sim.h"
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* 定义WDG时钟源
|
||||
*
|
||||
*//*! @WDG时钟源
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
|
||||
#define WDOG_CLK_BUS 0 /*!< 总线时钟 */
|
||||
#define WDOG_CLK_INTERNAL_32KHZ 2 /*!< 内部 32 kHz (ICSIRCLK) */
|
||||
#define WDOG_CLK_INTERNAL_1KHZ 1 /*!< 内部 LPO 1 KHz */
|
||||
#define WDOG_CLK_EXTERNAL 3 /*!< 外部时钟 */
|
||||
/*! @} */
|
||||
|
||||
/* 看门狗时钟源选择 */
|
||||
#define WDOG_CLK (WDOG_CLK_INTERNAL_1KHZ)
|
||||
|
||||
/* 看门狗寄存器默认值设置 */
|
||||
#define WDOG_CS1_DEFAULT_VALUE 0x80
|
||||
#define WDOG_CS2_DEFAULT_VALUE 0x01
|
||||
#define WDOG_TOVAL_DEFAULT_VALUE 0x0400
|
||||
#define WDOG_WIN_DEFAULT_VALUE 0x0000
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 看门狗解锁.
|
||||
*/
|
||||
#define WDOG_Unlock() DisableInterrupts; WDOG->CNT = 0x20C5; WDOG->CNT = 0x28D9; EnableInterrupts //Modify
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
* define 看门狗配置结构体
|
||||
*
|
||||
*//*! @看门狗配置结构体
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
typedef struct {
|
||||
struct {
|
||||
uint16_t bIntEnable : 1; /*!< 看门狗中断使能 */
|
||||
uint16_t bDisable : 1; /*!< 禁用看门狗 */
|
||||
uint16_t bWaitEnable : 1; /*!< 使能看门狗等待模式 */
|
||||
uint16_t bStopEnable : 1; /*!< 使能看门狗停止模式 */
|
||||
uint16_t bDbgEnable : 1; /*!< 使能看门狗调试模式 */
|
||||
uint16_t bWinEnable : 1; /*!< 使能看门狗窗口模式 */
|
||||
uint16_t bUpdateEnable : 1; /*!< 使能允许看门狗更新 */
|
||||
uint16_t bClkSrc : 2; /*!< 看门狗时钟源选择 */
|
||||
uint16_t bPrescaler : 1; /*!< 预分频系数 */
|
||||
}sBits; /*!< 位域结构体 */
|
||||
uint16_t u16ETMeOut; /*!< 看门狗超时值 */
|
||||
uint16_t u16WinETMe; /*!< 看门狗窗口值 */
|
||||
} WDOG_ConfigType, *WDOG_ConfigPtr; /*!< 看门狗配置结构体类型 */
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置看门狗超时值.
|
||||
*
|
||||
* @param[in] u16ETMeOut 超时值.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void WDOG_SetETMeOut(uint16_t u16ETMeOut)
|
||||
{
|
||||
WDOG->CNT = 0x20C5;
|
||||
WDOG->CNT = 0x28D9;
|
||||
WDOG->TOVAL8B.TOVALL = u16ETMeOut;
|
||||
WDOG->TOVAL8B.TOVALH = u16ETMeOut >> 8;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置看门狗窗口.
|
||||
*
|
||||
* @param[in] u16WinETMe 看门狗窗口值.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void WDOG_SetWindow(uint16_t u16WinETMe)
|
||||
{
|
||||
WDOG->CNT = 0x20C5;
|
||||
WDOG->CNT = 0x28D9;
|
||||
WDOG->WIN8B.WINL = u16WinETMe;
|
||||
WDOG->WIN8B.WINH = u16WinETMe >> 8;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查看门狗是否复位.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return TRUE 当看门狗复位发生, FALSE 无.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE uint8_t WDOG_IsReset(void)
|
||||
{
|
||||
if(SIM_GetStatus(SIM_SRSID_WDOG_MASK))
|
||||
{
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
void WDOG_Init(WDOG_ConfigPtr pConfig);
|
||||
void WDOG_DeInit(void);
|
||||
void WDOG_Disable(void);
|
||||
void WDOG_DisableWDOGEnableUpdate(void);
|
||||
void WDOG_Enable(void);
|
||||
void WDOG_Feed(void);
|
||||
void WDOG_SetETMeOut(uint16_t u16ETMeOut);
|
||||
void WDOG_SetWindow(uint16_t u16WinETMe);
|
||||
void WDOG_EnableUpdate(void);
|
||||
void WDOG_DisableUpdate(void);
|
||||
uint8_t WDOG_IsReset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
#endif /* __WDOG_H__ */
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
* 实验名称:模拟比较实验
|
||||
* 实验平台:NV32开发板
|
||||
* 板载芯片:NV32F100FL64E
|
||||
* 实验效果:选择ACMP正负输入,初始化ACMP模块,正负输入引脚输入数据开始
|
||||
* 比较,比较完成产生中断,在中断服务函数中清除中断标志位
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "acmp.h"
|
||||
#include "pmc.h"
|
||||
#include "sysinit.h"
|
||||
|
||||
int main (void);
|
||||
void FunForCallback(void);
|
||||
|
||||
/********************************************************************/
|
||||
int main (void)
|
||||
{
|
||||
ACMP_ConfigType ACMP_Config;
|
||||
PMC_ConfigType PMC_Config={0};
|
||||
|
||||
/*系统初始化*/
|
||||
sysinit();
|
||||
PMC_Config.sCtrlstatus.bits.bBandgapEn = 1; //使能带隙
|
||||
PMC_Config.sCtrlstatus.bits.bLvdStopEn = 0; //低压检测在停止模式下禁用
|
||||
PMC_Config.sCtrlstatus.bits.bLvdRstEn = 0; //禁用低压检测复位
|
||||
PMC_Init(PMC, &PMC_Config); //初始化PMC模块
|
||||
PMC_DisableLVWInterrupt(PMC); //禁用低压报警中断
|
||||
|
||||
printf("\nRunning the ACMP_demo project.\r\n");
|
||||
|
||||
|
||||
/*初始化ACMP模块 */
|
||||
ACMP_Config.sCtrlStatus.bits.bIntEn = TRUE; /*使能中断*/
|
||||
ACMP_Config.sCtrlStatus.bits.bMod= 1; /*中断在输出上升沿触发*/
|
||||
ACMP_Config.sCtrlStatus.bits.bOutEn = 1; /* ACMP输出置于外部引脚 */
|
||||
ACMP_Config.sPinSelect.bits.bNegPin = 0x3; /* 负输入引脚:DAC */
|
||||
ACMP_Config.sPinSelect.bits.bPosPin = 0; /* 正输入引脚:外部基准0,ACMP0_IN0-PTA0 */
|
||||
ACMP_Config.sDacSet.bits.bEn = TRUE; /* 使能 DAC */
|
||||
ACMP_Config.sDacSet.bits.bRef = DAC_REF_VDDA; /* DAC基准电压选择:Vdda */
|
||||
ACMP_Config.sDacSet.bits.bVal = 0x1F; /* DAC输出电平位:Vin/2 */
|
||||
ACMP_Config.sPinEnable.bits.bEn = TRUE; /* 使能外部基准0引脚输入 */
|
||||
|
||||
ACMP_SetCallback(ACMP0,FunForCallback); /*注册回调函数*/
|
||||
|
||||
ACMP_Init(ACMP0, &ACMP_Config); /*初始化ACMP模块*/
|
||||
|
||||
ACMP_Enable(ACMP0); /*使能ACMP */
|
||||
|
||||
/************************************************************
|
||||
printf("\nEnter stop mode and will be woken up by ACMP Irq.\r\n");
|
||||
PMC_SetMode(PMC,PmcModeStop3); //MCU进入停止模式,通过ACMP中断唤醒
|
||||
printf("\nWake up now.\r\n");
|
||||
*******************************************************************/
|
||||
while(1);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP回调函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void FunForCallback(void)
|
||||
{
|
||||
if(ACMP_GetFlag(ACMP0))
|
||||
{
|
||||
ACMP_ClrFlag(ACMP0); //清除中断标志位
|
||||
}
|
||||
|
||||
printf("\nCallback happens.\r\n");
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief Define interrupt service routines referenced by the vector table.
|
||||
*
|
||||
* Note: Only "vectors.c" should include this header file.
|
||||
*
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __ISR_H
|
||||
#define __ISR_H
|
||||
|
||||
/******************************************************************************
|
||||
* Macros
|
||||
******************************************************************************/
|
||||
/* Example */
|
||||
/*
|
||||
#undef VECTOR_036
|
||||
#define VECTOR_036 RTC_Isr
|
||||
|
||||
// ISR(s) are defined in your project directory.
|
||||
extern void RTC_Isr(void);
|
||||
*/
|
||||
|
||||
#undef VECTOR_032
|
||||
#define VECTOR_032 ACMP0_Isr
|
||||
|
||||
#undef VECTOR_037
|
||||
#define VECTOR_037 ACMP1_Isr
|
||||
|
||||
extern void ACMP0_Isr(void);
|
||||
extern void ACMP1_Isr(void);
|
||||
|
||||
#endif /*__ISR_H */
|
||||
|
||||
/* End of "isr.h" */
|
||||
@@ -0,0 +1,104 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
* 实验名称:模数转换试验(FIFO模式软件触发)
|
||||
* 实验平台:NV32开发板
|
||||
* 板载芯片:NV32F100FL64E
|
||||
* 实验效果:FIFO深度设定为3级,初始化ADC模块后,当FIFO采集数据满则开始
|
||||
* 转换,然后通过读取转换结果寄存器读取FIFO中的转换结果。每次
|
||||
* 读取一个转换结果读取3次
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "ics.h"
|
||||
#include "rtc.h"
|
||||
#include "uart.h"
|
||||
#include "adc.h"
|
||||
#include "pmc.h"
|
||||
#include "sysinit.h"
|
||||
|
||||
/**********************************************************************/
|
||||
uint16_t u16ADC_ConversionBuff[16];
|
||||
uint16_t u16ADC_ConversionCount = 0;
|
||||
volatile uint8_t u8ADC_ConversionFlag = 0;
|
||||
|
||||
int main (void);
|
||||
void ADC_CallBack( void );
|
||||
/******************************************************************************/
|
||||
|
||||
int main (void)
|
||||
{
|
||||
uint8_t u8Ch;
|
||||
ADC_ConfigType sADC_Config = {0};
|
||||
|
||||
/*系统初始化*/
|
||||
sysinit();
|
||||
printf("\nRunning the ADC_FIFO_demo project.\r\n");
|
||||
|
||||
UART_WaitTxComplete(TERM_PORT);
|
||||
|
||||
/*初始化ADC模块*/
|
||||
sADC_Config.u8ClockDiv = ADC_ADIV_DIVIDE_8; /*!< ADC时钟源分频系数为8*/
|
||||
sADC_Config.u8ClockSource = CLOCK_SOURCE_ADACK; /*!< ADC时钟源选择异步时钟*/
|
||||
sADC_Config.u8Mode = ADC_MODE_12BIT; /*!< 12位转换*/
|
||||
sADC_Config.sSetting.bIntEn = 1; /*!< 使能中断*/
|
||||
sADC_Config.u8FiFoLevel = ADC_FIFO_LEVEL3; /*!< 3级FIFO */
|
||||
ADC_SetCallBack(ADC_CallBack);
|
||||
ADC_Init( ADC, &sADC_Config); /*!< 初始化ADC*/
|
||||
|
||||
|
||||
while(1)
|
||||
{
|
||||
/*选择通道开始转换*/
|
||||
u8ADC_ConversionFlag = 0;
|
||||
ADC_SetChannel(ADC,ADC_CHANNEL_AD22_TEMPSENSOR);
|
||||
ADC_SetChannel(ADC,ADC_CHANNEL_AD29_VREFH);
|
||||
ADC_SetChannel(ADC,ADC_CHANNEL_AD30_VREFL);
|
||||
/*等待转化完成 */
|
||||
while( !u8ADC_ConversionFlag);
|
||||
|
||||
printf("ADC conversion result as below:\r\n");
|
||||
for( u8Ch =0 ;u8Ch< u16ADC_ConversionCount; u8Ch ++)
|
||||
{
|
||||
|
||||
printf("0x%x,",u16ADC_ConversionBuff[u8Ch]);
|
||||
}
|
||||
printf("\r\n");
|
||||
printf("input any character to start a new conversion!\r\n");
|
||||
// u8Ch = UART_GetChar(TERM_PORT);
|
||||
u16ADC_ConversionCount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
*
|
||||
* @brief ADC回调函数中,在回调函数里读取转换结果
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
void ADC_CallBack( void )
|
||||
{
|
||||
|
||||
while( !ADC_IsFIFOEmptyFlag(ADC) ) //结果FIFO中有有效的新数据
|
||||
{
|
||||
if( u16ADC_ConversionCount < 3 ) //读取转换结果,将结果FIFO中的数据全部读出
|
||||
{
|
||||
u16ADC_ConversionBuff[u16ADC_ConversionCount++] = ADC_ReadResultReg(ADC);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADC_ReadResultReg(ADC); //读转换结果寄存器
|
||||
}
|
||||
}
|
||||
|
||||
u8ADC_ConversionFlag = 1;
|
||||
}
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,29 @@
|
||||
/******************************************************************************
|
||||
* File: isr.h
|
||||
* Purpose: Define interrupt service routines referenced by the vector table.
|
||||
* Note: Only "vectors.c" should include this header file.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __ISR_H
|
||||
#define __ISR_H 1
|
||||
|
||||
|
||||
/* Example */
|
||||
/*
|
||||
#undef VECTOR_036
|
||||
#define VECTOR_036 RTC_Isr
|
||||
|
||||
// ISR(s) are defined in your project directory.
|
||||
extern void RTC_Isr(void);
|
||||
*/
|
||||
|
||||
#undef VECTOR_036
|
||||
#define VECTOR_036 RTC_Isr
|
||||
#undef VECTOR_031
|
||||
#define VECTOR_031 ADC_Isr
|
||||
|
||||
extern void RTC_Isr(void);
|
||||
extern void ADC_Isr(void);
|
||||
#endif //__ISR_H
|
||||
|
||||
/* End of "isr.h" */
|
||||
@@ -0,0 +1,164 @@
|
||||
/********************************************************************************
|
||||
*
|
||||
* 实验名称:硬件触发ADC转换(FIFO模式)
|
||||
* 实验平台:NV32开发板
|
||||
* 板载芯片:NV32F100FL64E
|
||||
* 实验效果:设定FIFO深度,初始化ADC模块,ADC开始采集数据放入FIFO中,FIFO满
|
||||
后等待硬件触发信号。
|
||||
1:单次转换模式, 当ADC检测到第一个硬件触发信号后,开始转换FIFO
|
||||
中第一个数据,检测到第二个硬件触发信号后,开始
|
||||
转换FIFO中第2个数据,以此类推直到FIFO中的数据全部
|
||||
转换完,然后触发ADC中断读取转换结果。当转换完成后,
|
||||
如果出现新的触发脉冲,将生产新的转换集合。
|
||||
例:当FIFO深度设定为3时,ADC要检测到三个硬件触发信号
|
||||
才能将FIFO中的数据全部转换完成,然后产生中断。
|
||||
2:连续转换模式, 当出现硬件触发信号时,会触发ADC连续采样,建议在使用
|
||||
FIFO数据模式时,在中断服务函数中读取FIFO结果前禁用ADC
|
||||
硬件触发使能,在读取完FIFO结果之后再打开硬件触发使能,
|
||||
避免数据错乱。
|
||||
***********************************************************************************/
|
||||
#include "common.h"
|
||||
#include "ics.h"
|
||||
#include "sim.h"
|
||||
#include "rtc.h"
|
||||
#include "pit.h"
|
||||
#include "uart.h"
|
||||
#include "adc.h"
|
||||
#include "etm.h"
|
||||
#include "sysinit.h"
|
||||
|
||||
uint16_t u16ADC_ConversionBuff[16];
|
||||
uint16_t u16ADC_ConversionCount = 0;
|
||||
volatile uint8_t u8ADC_ConversionFlag = 0;
|
||||
|
||||
int main (void);
|
||||
void ADC_CallBack( void );
|
||||
/********************************************************************/
|
||||
int main (void)
|
||||
{
|
||||
uint16_t u16ModuloValue;
|
||||
uint32_t u32LoadValue0;
|
||||
ADC_ConfigType sADC_Config = {0};
|
||||
RTC_ConfigType sRTCConfig;
|
||||
RTC_ConfigType *pRTC_Config=&sRTCConfig;
|
||||
PIT_ConfigType sPITConfig0;
|
||||
PIT_ConfigType *pPIT_Config0 =&sPITConfig0;
|
||||
|
||||
/*系统初始化*/
|
||||
sysinit();
|
||||
|
||||
|
||||
printf("\nRunning the ADC_HWT_demo project.\r\n");
|
||||
/*********************ADC硬件触发源选择**********************************/
|
||||
/**************************************************************************
|
||||
*注:ETM2通道4与NMI中断输入引脚共用PB4,当选择ETM2通道4作为ADC硬件触发源时,
|
||||
* 需要禁用NMI中断输入引脚
|
||||
****************************************************************************/
|
||||
SIM_TriggerADCByRTC(); //选择RTC溢出触发ADC转换
|
||||
//SIM_TriggerADCByPIT(); //选择PIT溢出触发ADC
|
||||
//SIM_TriggerADCByETM2Init(); //选择ETM2初始后延时一段时间触发ADC转换
|
||||
//SIM_TriggerADCByETM2Match(); //选择ETM2匹配后延时一段时间触发ADC转换
|
||||
|
||||
/**********设置ETM2从匹配/初始化到触发ADC转换的延时时间*****************/
|
||||
SIM_SetClockOutputDivide(0x07); //总线时钟输出分频
|
||||
SIM_DelayETM2Trig2ADC(0xff); //延时计数模数值
|
||||
|
||||
UART_WaitTxComplete(TERM_PORT);
|
||||
LED0_Init();
|
||||
|
||||
/* 初始化ADC模块*/
|
||||
sADC_Config.u8ClockDiv = ADC_ADIV_DIVIDE_8; /*!< ADC时钟源分频系数为8 */
|
||||
sADC_Config.u8ClockSource = CLOCK_SOURCE_ADACK; /*!< ADC时钟源选择异步时钟 */
|
||||
sADC_Config.u8Mode = ADC_MODE_12BIT; /*!< 12位转换 */
|
||||
sADC_Config.sSetting.bIntEn = 1; /*!< 使能中断*/
|
||||
sADC_Config.u8FiFoLevel = ADC_FIFO_LEVEL3; /*!< 3级FIFO */
|
||||
sADC_Config.sSetting.bContinuousEn=0; /*!< 单次转换模式 */
|
||||
sADC_Config.sSetting.bHardwareTriggerEn=1; /*!< 使能硬件触发模式 */
|
||||
ADC_SetCallBack(ADC_CallBack);
|
||||
ADC_Init( ADC, &sADC_Config); //初始化ADC模块
|
||||
|
||||
/*RTC溢出触发ADC */
|
||||
|
||||
u16ModuloValue = 0x09;
|
||||
pRTC_Config->u16ModuloValue = u16ModuloValue; //设定模数值
|
||||
pRTC_Config->bInterruptEn=0; //禁用中断
|
||||
pRTC_Config->bClockSource = RTC_CLKSRC_1KHZ; //选择1KHz时钟源
|
||||
pRTC_Config->bClockPresaler = RTC_CLK_PRESCALER_100; //时钟分频系数100
|
||||
RTC_Init(pRTC_Config);
|
||||
|
||||
|
||||
/*PIT0溢出触发ADC */
|
||||
/*
|
||||
u32LoadValue0 = 0xFFFFFF; //设定装载值
|
||||
pPIT_Config0->u32LoadValue = u32LoadValue0;
|
||||
pPIT_Config0->bFreeze = FALSE; //在调试模式时仍然运行
|
||||
pPIT_Config0->bModuleDis = FALSE; //使能PIT模块
|
||||
pPIT_Config0->bChainMode = FALSE; //禁用链模式
|
||||
pPIT_Config0->bInterruptEn = FALSE; //禁用中断
|
||||
pPIT_Config0->bETMerEn = TRUE; //使能PIT通道
|
||||
PIT_Init(PIT_CHANNEL0, pPIT_Config0);
|
||||
*/
|
||||
/*选择ETM2匹配触发*/
|
||||
/*
|
||||
ETM_PWMInit(ETM2, ETM_PWMMODE_EDGEALLIGNED, ETM_PWM_HIGHTRUEPULSE);
|
||||
ETM_SetETMEnhanced(ETM2);
|
||||
ETM2->EXTTRIG |= ETM_EXTTRIG_CH1TRIG_MASK;//使能通道1匹配触发
|
||||
ETM_SetModValue(ETM2, 29999); // 设置ETM2模值
|
||||
ETM_SetChannelValue(ETM2, ETM_CHANNEL_CHANNEL1, 5000); //设置ETM2通道值
|
||||
ETM_ClockSet(ETM2, ETM_CLOCK_SYSTEMCLOCK, ETM_CLOCK_PS_DIV128); //设置ETM2模块时钟源及分频系数.
|
||||
NVIC_DisableIRQ(ETM2_IRQn);
|
||||
*/
|
||||
/*选择ETM2初始触发*/
|
||||
/*
|
||||
ETM_PWMInit(ETM2, ETM_PWMMODE_EDGEALLIGNED, ETM_PWM_HIGHTRUEPULSE);
|
||||
ETM_SetETMEnhanced(ETM2);
|
||||
ETM_SetCounterInitValue(ETM2, 3000);
|
||||
ETM2->EXTTRIG |= ETM_EXTTRIG_INITTRIGEN_MASK; //初始化触发使能
|
||||
ETM_SetModValue(ETM2, 9999); // 设置ETM2模值
|
||||
ETM_SetChannelValue(ETM2, ETM_CHANNEL_CHANNEL1, 5000); //设置ETM2通道值
|
||||
ETM_ClockSet(ETM2, ETM_CLOCK_SYSTEMCLOCK, ETM_CLOCK_PS_DIV128); //设置ETM2模块时钟源及分频系数.
|
||||
*/
|
||||
|
||||
/***********设置转换通道,等待触发信号 ***********************/
|
||||
ADC_SetChannel(ADC,ADC_CHANNEL_AD22_TEMPSENSOR);
|
||||
ADC_SetChannel(ADC,ADC_CHANNEL_AD29_VREFH);
|
||||
ADC_SetChannel(ADC,ADC_CHANNEL_AD30_VREFL);
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
/***************************************************************************
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
*
|
||||
* @brief ADC回调函数中,在回调函数里读取转换结果
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_CallBack( void )
|
||||
{
|
||||
uint8_t u8Ch;
|
||||
LED0_Toggle();
|
||||
while( !ADC_IsFIFOEmptyFlag(ADC) ) ////结果FIFO中有有效的新数据
|
||||
{
|
||||
if( u16ADC_ConversionCount < 3 ) //读取转换结果,将结果FIFO中的数据全部读出
|
||||
{
|
||||
u16ADC_ConversionBuff[u16ADC_ConversionCount++] = ADC_ReadResultReg(ADC);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADC_ReadResultReg(ADC);
|
||||
}
|
||||
}
|
||||
/*打印转换结果*/
|
||||
printf("ADC conversion result as below:\r\n");
|
||||
for( u8Ch =0 ; u8Ch< u16ADC_ConversionCount; u8Ch ++)
|
||||
{
|
||||
printf("0x%x,",u16ADC_ConversionBuff[u8Ch]);
|
||||
}
|
||||
printf("\r\n");
|
||||
u16ADC_ConversionCount = 0;;
|
||||
}
|
||||
/********************************************************************/
|
||||
@@ -0,0 +1,31 @@
|
||||
/******************************************************************************
|
||||
* File: isr.h
|
||||
* Purpose: Define interrupt service routines referenced by the vector table.
|
||||
* Note: Only "vectors.c" should include this header file.
|
||||
******************************************************************************/
|
||||
#ifndef __ISR_H
|
||||
#define __ISR_H 1
|
||||
/* Example */
|
||||
/*
|
||||
#undef VECTOR_036
|
||||
#define VECTOR_036 RTC_Isr
|
||||
// ISR(s) are defined in your project directory.
|
||||
extern void RTC_Isr(void);
|
||||
*/
|
||||
#undef VECTOR_035
|
||||
#define VECTOR_035 ETM2_Isr /*!< Vector 35 points to ETM2 interrupt service routine */
|
||||
#undef VECTOR_036
|
||||
#define VECTOR_036 RTC_Isr
|
||||
#undef VECTOR_031
|
||||
#define VECTOR_031 ADC_Isr
|
||||
#undef VECTOR_038
|
||||
#define VECTOR_038 PIT_Ch0Isr /*!< Vector 38 points to PIT channel 0 interrupt service routine */
|
||||
#undef VECTOR_039
|
||||
#define VECTOR_039 PIT_Ch1Isr /*!< Vector 39 points to PIT channel 1 interrupt service routine */
|
||||
extern void ETM2_Isr(void);
|
||||
extern void RTC_Isr(void);
|
||||
extern void ADC_Isr(void);
|
||||
extern void PIT_Ch1Isr(void);
|
||||
extern void PIT_Ch0Isr(void);
|
||||
#endif //__ISR_H
|
||||
/* End of "isr.h" */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user