This commit is contained in:
supperthomas
2020-02-15 18:33:43 +08:00
2457 changed files with 2135389 additions and 25245 deletions

View File

@@ -15,7 +15,7 @@
* within TencentOS. * within TencentOS.
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#include <tos_k.h> #include "tos_k.h"
__API__ uint32_t tos_cpu_clz(uint32_t val) __API__ uint32_t tos_cpu_clz(uint32_t val)
{ {

View File

@@ -0,0 +1,43 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_ARM_H_
#define _TOS_ARM_H_
#define DSB __ASM__ __VOLATILE__("dsb" ::: "memory")
#define DMB __ASM__ __VOLATILE__("dmb" ::: "memory")
#define ISB __ASM__ __VOLATILE__("isb" ::: "memory")
#define __STRINGIFY(x) #x
#define ARM_MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \
__ASM__ __VOLATILE__ ("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: : "r" (src) )
#define ARM_MRC(coproc, opcode_1, CRn, CRm, opcode_2) \
({ \
uint32_t __dst; \
__ASM__ __VOLATILE__ ("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: "=r" (__dst) ); \
__dst; \
})
#endif /* _TOS_ARM_H_ */

View File

@@ -0,0 +1,27 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_CHIP_H_
#define _TOS_CHIP_H_
#include "chip/gic.h"
#include "chip/chip.h"
void chip_init(void);
#endif /* _TOS_CHIP_H_ */

View File

@@ -0,0 +1,145 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_CPU_H_
#define _TOS_CPU_H_
#include "tos_arm.h"
#include "tos_chip.h"
#include "tos_gic.h"
#include "tos_interrupt.h"
typedef struct cpu_context_st {
cpu_data_t r0;
cpu_data_t r1;
cpu_data_t r2;
cpu_data_t r3;
cpu_data_t r4;
cpu_data_t r5;
cpu_data_t r6;
cpu_data_t r7;
cpu_data_t r8;
cpu_data_t r9;
cpu_data_t r10;
cpu_data_t r11;
cpu_data_t r12;
cpu_data_t lr;
cpu_data_t pc;
cpu_data_t cpsr;
} cpu_context_t;
__API__ uint32_t tos_cpu_clz(uint32_t val);
__API__ void tos_cpu_int_disable(void);
__API__ void tos_cpu_int_enable(void);
__API__ cpu_cpsr_t tos_cpu_cpsr_save(void);
__API__ void tos_cpu_cpsr_restore(cpu_cpsr_t cpsr);
#if (TOS_CFG_CPU_HRTIMER_EN > 0u)
__API__ void tos_cpu_hrtimer_init(void);
__API__ cpu_hrtimer_t tos_cpu_hrtimer_read(void);
#endif
__KERNEL__ void cpu_init(void);
__KERNEL__ void cpu_reset(void);
__KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick);
__KERNEL__ void cpu_sched_start(void);
__KERNEL__ void cpu_context_switch(void);
__KERNEL__ void cpu_irq_context_switch(void);
#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u
__KERNEL__ k_err_t cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth);
#endif
__KERNEL__ k_stack_t *cpu_task_stk_init(void *entry,
void *arg,
void *exit,
k_stack_t *stk_base,
size_t stk_size);
#if TOS_CFG_TICKLESS_EN > 0u
__KERNEL__ void cpu_systick_resume(void);
__KERNEL__ void cpu_systick_suspend(void);
__KERNEL__ void cpu_systick_reload_reset(void);
__KERNEL__ void cpu_systick_pending_reset(void);
__KERNEL__ k_time_t cpu_systick_max_delay_millisecond(void);
__KERNEL__ void cpu_systick_expires_set(k_time_t millisecond);
__KERNEL__ void cpu_systick_reset(void);
#endif
#if TOS_CFG_PWR_MGR_EN > 0u
__KERNEL__ void cpu_sleep_mode_enter(void);
__KERNEL__ void cpu_stop_mode_enter(void);
__KERNEL__ void cpu_standby_mode_enter(void);
#endif
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
__KERNEL__ void cpu_flush_fpu(void);
#endif /* TOS_CFG_CPU_ARM_FPU_EN */
__KERNEL__ void cpu_fault_diagnosis(void);
#endif
/* Allocates CPU status register word. */
#define TOS_CPU_CPSR_ALLOC() cpu_cpsr_t cpu_cpsr = (cpu_cpsr_t)0u
/* Save CPU status word & disable interrupts.*/
#define TOS_CPU_INT_DISABLE() \
do { \
cpu_cpsr = tos_cpu_cpsr_save(); \
} while (0)
/* Restore CPU status word. */
#define TOS_CPU_INT_ENABLE() \
do { \
tos_cpu_cpsr_restore(cpu_cpsr); \
} while (0)
#endif /* _TOS_CPU_H_ */

View File

@@ -0,0 +1,34 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_CPU_DEF_H_
#define _TOS_CPU_DEF_H_
enum CPU_WORD_SIZE {
CPU_WORD_SIZE_08,
CPU_WORD_SIZE_16,
CPU_WORD_SIZE_32,
CPU_WORD_SIZE_64,
};
enum CPU_STK_GROWTH {
CPU_STK_GROWTH_ASCENDING,
CPU_STK_GROWTH_DESCENDING,
};
#endif /* _TOS_CPU_DEF_H_ */

View File

@@ -0,0 +1,57 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_CPU_TYPES_H_
#define _TOS_CPU_TYPES_H_
/* CPU address type based on address bus size. */
#if (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_32)
typedef uint32_t cpu_addr_t;
#elif (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_16)
typedef uint16_t cpu_addr_t;
#else
typedef uint8_t cpu_addr_t;
#endif
/* CPU data type based on data bus size. */
#if (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_32)
typedef uint32_t cpu_data_t;
#elif (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_16)
typedef uint16_t cpu_data_t;
#else
typedef uint8_t cpu_data_t;
#endif
#if (TOS_CFG_CPU_HRTIMER_EN > 0)
#if (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_08)
typedef uint8_t cpu_hrtimer_t;
#elif (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_16)
typedef uint16_t cpu_hrtimer_t;
#elif (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_64)
typedef uint64_t cpu_hrtimer_t;
#else
typedef uint32_t cpu_hrtimer_t;
#endif
#else
typedef uint32_t cpu_hrtimer_t;
#endif
//typedef cpu_addr_t size_t;
typedef cpu_addr_t cpu_cpsr_t;
#endif

View File

@@ -0,0 +1,236 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_FAULT_H_
#define _TOS_FAULT_H_
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
typedef int (*k_fault_log_writer_t)(const char *format, ...);
#define K_FAULT_STACK_DUMP_DEPTH 10u
#define K_FAULT_CALL_STACK_BACKTRACE_DEPTH 5u
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
typedef struct fault_fpu_frame_st {
cpu_data_t s0;
cpu_data_t s1;
cpu_data_t s2;
cpu_data_t s3;
cpu_data_t s4;
cpu_data_t s5;
cpu_data_t s6;
cpu_data_t s7;
cpu_data_t s8;
cpu_data_t s9;
cpu_data_t s10;
cpu_data_t s11;
cpu_data_t s12;
cpu_data_t s13;
cpu_data_t s14;
cpu_data_t s15;
cpu_data_t fpscr;
} fault_fpu_frame_t;
#endif
typedef struct fault_cpu_frame_st {
cpu_data_t r0;
cpu_data_t r1;
cpu_data_t r2;
cpu_data_t r3;
cpu_data_t r12;
cpu_data_t lr;
cpu_data_t pc;
cpu_data_t spsr;
} fault_cpu_frame_t;
typedef struct fault_exc_frame_st {
fault_cpu_frame_t cpu_frame;
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
fault_fpu_frame_t fpu_frame;
#endif
} fault_exc_frame_t;
/**
* information we need to do fault backtrace
*/
typedef struct fault_information_st {
int is_thumb : 1; /**< whether it is thumb we use when we fall into fault? */
int is_on_task : 1; /**< whether we are on a task when fall into fault? */
int is_stk_ovrf : 1; /**< whether we get a stack overflow */
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
int is_ext_stk_frm : 1; /**< whether it is a extended stack frame?(whether the cpu has pushed fpu registers onto the stack) */
#endif
cpu_addr_t pc; /**< just where fault happens */
cpu_addr_t sp_before_fault; /**< original sp just before the cpu push the fault exception frame */
/**
* we need main_stack_start & main_stack_limit to do call stack backtrace
* when we fall into fault during a task, we should do the call stack backtrace on the task's stack
* but if not, which means we are in kernel, we should do the call stack backtrace on the main stack
* in arm v7-m, this should be the MSP's start and limit
* in arm v7-a, call stack backtrace is another story(much more elegant because we have FP).
*/
cpu_addr_t stack_start; /**< current sp start address we use. if on task, it'll be the task's stack, otherwise it'll be the msp */
cpu_addr_t stack_limit; /**< current sp limit address */
cpu_addr_t code_start; /**< current code start address */
cpu_addr_t code_limit; /**< current code limit address */
} fault_info_t;
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
#define DEFAULT_CODE_SECTION_NAME ER_IROM1
#define DEFAULT_CSTACK_SECTION_NAME STACK
#define SECTION_START(_name_) _name_##$$Base
#define SECTION_END(_name_) _name_##$$Limit
#define IMAGE_SECTION_START(_name_) Image$$##_name_##$$Base
#define IMAGE_SECTION_END(_name_) Image$$##_name_##$$Limit
#define CSTACK_BLOCK_START(_name_) SECTION_START(_name_)
#define CSTACK_BLOCK_END(_name_) SECTION_END(_name_)
#define CODE_SECTION_START(_name_) IMAGE_SECTION_START(_name_)
#define CODE_SECTION_END(_name_) IMAGE_SECTION_END(_name_)
extern const int CSTACK_BLOCK_START(DEFAULT_CSTACK_SECTION_NAME);
extern const int CSTACK_BLOCK_END(DEFAULT_CSTACK_SECTION_NAME);
extern const int CODE_SECTION_START(DEFAULT_CODE_SECTION_NAME);
extern const int CODE_SECTION_END(DEFAULT_CODE_SECTION_NAME);
__STATIC_INLINE__ cpu_addr_t fault_code_start(void)
{
return (cpu_addr_t)&CODE_SECTION_START(DEFAULT_CODE_SECTION_NAME);
}
__STATIC_INLINE__ cpu_addr_t fault_code_limit(void)
{
return (cpu_addr_t)&CODE_SECTION_END(DEFAULT_CODE_SECTION_NAME);
}
__STATIC_INLINE__ cpu_addr_t fault_msp_start(void)
{
return (cpu_addr_t)&CSTACK_BLOCK_START(DEFAULT_CSTACK_SECTION_NAME);
}
__STATIC_INLINE__ cpu_addr_t fault_msp_limit(void)
{
return (cpu_addr_t)&CSTACK_BLOCK_END(DEFAULT_CSTACK_SECTION_NAME);
}
#elif defined(__ICCARM__)
#define DEFAULT_CODE_SECTION_NAME ".text"
#define DEFAULT_CSTACK_SECTION_NAME "CSTACK"
#pragma section=DEFAULT_CSTACK_SECTION_NAME
#pragma section=DEFAULT_CODE_SECTION_NAME
__STATIC_INLINE__ cpu_addr_t fault_code_start(void)
{
return (cpu_addr_t)__section_begin(DEFAULT_CODE_SECTION_NAME);
}
__STATIC_INLINE__ cpu_addr_t fault_code_limit(void)
{
return (cpu_addr_t)__section_end(DEFAULT_CODE_SECTION_NAME);
}
__STATIC_INLINE__ cpu_addr_t fault_msp_start(void)
{
return (cpu_addr_t)__section_begin(DEFAULT_CSTACK_SECTION_NAME);
}
__STATIC_INLINE__ cpu_addr_t fault_msp_limit(void)
{
return (cpu_addr_t)__section_end(DEFAULT_CSTACK_SECTION_NAME);
}
#elif defined(__GNUC__)
/**
* if we are using keil(armcc) or mdk(iccarm), we probably use the defult link script supplied by the IDE.
* the way to locate the text/stack section start and limit is to find them in default link script.
* but if we build our project by makefile(or something like scons, cmake, etc), we probably need to write
* our own link scrpit, if so, we should do like this(just a demo):
*
_stext = .;
.text : {
*(.text.startup)
*(.text)
*(.text.*)
}
_etext = .;
__bss_start = .;
.bss : {
*(.bss)
*(.bss.*)
*(COMMON)
_sstack = .;
*(.cstack)
_estack = .;
}
__bss_end = .;
* by this, we can locate text/stack section start and limit by _stext/_etext and _sstack/_estack
*/
#define DEFAULT_CODE_SECTION_START _stext
#define DEFAULT_CODE_SECTION_END _etext
#define DEFAULT_CSTACK_SECTION_START _sstack
#define DEFAULT_CSTACK_SECTION_END _estack
extern const int DEFAULT_CODE_SECTION_START;
extern const int DEFAULT_CODE_SECTION_END;
extern const int DEFAULT_CSTACK_SECTION_START;
extern const int DEFAULT_CSTACK_SECTION_END;
__STATIC_INLINE__ cpu_addr_t fault_code_start(void)
{
return (cpu_addr_t)(&(DEFAULT_CODE_SECTION_START));
}
__STATIC_INLINE__ cpu_addr_t fault_code_limit(void)
{
return (cpu_addr_t)(&(DEFAULT_CODE_SECTION_END));
}
__STATIC_INLINE__ cpu_addr_t fault_msp_start(void)
{
return (cpu_addr_t)(&(DEFAULT_CSTACK_SECTION_START));
}
__STATIC_INLINE__ cpu_addr_t fault_msp_limit(void)
{
return (cpu_addr_t)(&(DEFAULT_CSTACK_SECTION_END));
}
#endif
__API__ void tos_fault_log_writer_set(k_fault_log_writer_t log_writer);
__KERNEL__ int fault_default_log_writer(const char *format, ...);
__KERNEL__ void fault_backtrace(cpu_addr_t lr, fault_exc_frame_t *frame);
#endif
#endif /* _TOS_FAULT_H_ */

View File

@@ -0,0 +1,106 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_GIC_H_
#define _TOS_GIC_H_
typedef struct gic_distributor_registers_st {
uint32_t D_CTLR; /*!< Offset: 0x1000 (R/W) Distributor Control Register */
uint32_t D_TYPER; /*!< Offset: 0x1004 (R/ ) Interrupt Controller Type Register */
uint32_t D_IIDR; /*!< Offset: 0x1008 (R/ ) Distributor Implementer Identification Register */
uint32_t RESERVED1[29];
uint32_t D_IGROUPR[16]; /*!< Offset: 0x1080 - 0x0BC (R/W) Interrupt Group Registers */
uint32_t RESERVED2[16];
uint32_t D_ISENABLER[16]; /*!< Offset: 0x1100 - 0x13C (R/W) Interrupt Set-Enable Registers */
uint32_t RESERVED3[16];
uint32_t D_ICENABLER[16]; /*!< Offset: 0x1180 - 0x1BC (R/W) Interrupt Clear-Enable Registers */
uint32_t RESERVED4[16];
uint32_t D_ISPENDR[16]; /*!< Offset: 0x1200 - 0x23C (R/W) Interrupt Set-Pending Registers */
uint32_t RESERVED5[16];
uint32_t D_ICPENDR[16]; /*!< Offset: 0x1280 - 0x2BC (R/W) Interrupt Clear-Pending Registers */
uint32_t RESERVED6[16];
uint32_t D_ISACTIVER[16]; /*!< Offset: 0x1300 - 0x33C (R/W) Interrupt Set-Active Registers */
uint32_t RESERVED7[16];
uint32_t D_ICACTIVER[16]; /*!< Offset: 0x1380 - 0x3BC (R/W) Interrupt Clear-Active Registers */
uint32_t RESERVED8[16];
uint8_t D_IPRIORITYR[512]; /*!< Offset: 0x1400 - 0x5FC (R/W) Interrupt Priority Registers */
uint32_t RESERVED9[128];
uint8_t D_ITARGETSR[512]; /*!< Offset: 0x1800 - 0x9FC (R/W) Interrupt Targets Registers */
uint32_t RESERVED10[128];
uint32_t D_ICFGR[32]; /*!< Offset: 0x1C00 - 0xC7C (R/W) Interrupt configuration registers */
uint32_t RESERVED11[32];
uint32_t D_PPISR; /*!< Offset: 0x1D00 (R/ ) Private Peripheral Interrupt Status Register */
uint32_t D_SPISR[15]; /*!< Offset: 0x1D04 - 0xD3C (R/ ) Shared Peripheral Interrupt Status Registers */
uint32_t RESERVED12[112];
uint32_t D_SGIR; /*!< Offset: 0x1F00 ( /W) Software Generated Interrupt Register */
uint32_t RESERVED13[3];
uint8_t D_CPENDSGIR[16]; /*!< Offset: 0x1F10 - 0xF1C (R/W) SGI Clear-Pending Registers */
uint8_t D_SPENDSGIR[16]; /*!< Offset: 0x1F20 - 0xF2C (R/W) SGI Set-Pending Registers */
uint32_t RESERVED14[40];
uint32_t D_PIDR4; /*!< Offset: 0x1FD0 (R/ ) Peripheral ID4 Register */
uint32_t D_PIDR5; /*!< Offset: 0x1FD4 (R/ ) Peripheral ID5 Register */
uint32_t D_PIDR6; /*!< Offset: 0x1FD8 (R/ ) Peripheral ID6 Register */
uint32_t D_PIDR7; /*!< Offset: 0x1FDC (R/ ) Peripheral ID7 Register */
uint32_t D_PIDR0; /*!< Offset: 0x1FE0 (R/ ) Peripheral ID0 Register */
uint32_t D_PIDR1; /*!< Offset: 0x1FE4 (R/ ) Peripheral ID1 Register */
uint32_t D_PIDR2; /*!< Offset: 0x1FE8 (R/ ) Peripheral ID2 Register */
uint32_t D_PIDR3; /*!< Offset: 0x1FEC (R/ ) Peripheral ID3 Register */
uint32_t D_CIDR0; /*!< Offset: 0x1FF0 (R/ ) Component ID0 Register */
uint32_t D_CIDR1; /*!< Offset: 0x1FF4 (R/ ) Component ID1 Register */
uint32_t D_CIDR2; /*!< Offset: 0x1FF8 (R/ ) Component ID2 Register */
uint32_t D_CIDR3; /*!< Offset: 0x1FFC (R/ ) Component ID3 Register */
} gic_dist_t;
typedef struct gic_cpu_interface_registers_st {
uint32_t C_CTLR; /*!< Offset: 0x2000 (R/W) CPU Interface Control Register */
uint32_t C_PMR; /*!< Offset: 0x2004 (R/W) Interrupt Priority Mask Register */
uint32_t C_BPR; /*!< Offset: 0x2008 (R/W) Binary Point Register */
uint32_t C_IAR; /*!< Offset: 0x200C (R/ ) Interrupt Acknowledge Register */
uint32_t C_EOIR; /*!< Offset: 0x2010 ( /W) End Of Interrupt Register */
uint32_t C_RPR; /*!< Offset: 0x2014 (R/ ) Running Priority Register */
uint32_t C_HPPIR; /*!< Offset: 0x2018 (R/ ) Highest Priority Pending Interrupt Register */
uint32_t C_ABPR; /*!< Offset: 0x201C (R/W) Aliased Binary Point Register */
uint32_t C_AIAR; /*!< Offset: 0x2020 (R/ ) Aliased Interrupt Acknowledge Register */
uint32_t C_AEOIR; /*!< Offset: 0x2024 ( /W) Aliased End Of Interrupt Register */
uint32_t C_AHPPIR; /*!< Offset: 0x2028 (R/ ) Aliased Highest Priority Pending Interrupt Register */
uint32_t RESERVED15[41];
uint32_t C_APR0; /*!< Offset: 0x20D0 (R/W) Active Priority Register */
uint32_t RESERVED16[3];
uint32_t C_NSAPR0; /*!< Offset: 0x20E0 (R/W) Non-secure Active Priority Register */
uint32_t RESERVED17[6];
uint32_t C_IIDR; /*!< Offset: 0x20FC (R/ ) CPU Interface Identification Register */
uint32_t RESERVED18[960];
uint32_t C_DIR; /*!< Offset: 0x3000 ( /W) Deactivate Interrupt Register */
} gic_cpu_t;
typedef struct gic_data_st {
gic_dist_t *dist;
gic_cpu_t *cpu;
} gic_data_t;
__KERNEL__ uint32_t gic_interrupt_id_get(uint32_t gic_nr);
__KERNEL__ void gic_interrupt_end(uint32_t gic_nr, uint32_t vector);
__KERNEL__ int gic_init(uint32_t gic_nr);
__KERNEL__ void gic_interrupt_enable(uint32_t gic_nr, uint32_t vector);
__KERNEL__ void gic_interrupt_disable(uint32_t gic_nr, uint32_t vector);
#endif /* _TOS_GIC_H_ */

View File

@@ -0,0 +1,65 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_INTERRUPT_H_
#define _TOS_INTERRUPT_H_
typedef void (*int_handler_t)(void *arg);
typedef struct int_handle_st {
int_handler_t handler;
void *arg;
} int_handle_t;
typedef struct int_frame_st {
#if 0
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
uint32_t fpexc;
#endif
#endif
cpu_data_t r0;
cpu_data_t r1;
cpu_data_t r2;
cpu_data_t r3;
cpu_data_t r4;
cpu_data_t r5;
cpu_data_t r6;
cpu_data_t r7;
cpu_data_t r8;
cpu_data_t r9;
cpu_data_t r10;
cpu_data_t r11;
cpu_data_t r12;
cpu_data_t lr;
cpu_data_t pc;
cpu_data_t spsr;
} int_frame_t;
__KERNEL__ void interrupt_irq(int_frame_t *int_frame);
__KERNEL__ int interrupt_init(void);
__API__ int tos_interrupt_handler_register(uint32_t vector, int_handler_t handler, void *arg);
__API__ void tos_interrupt_enable(uint32_t vector);
__API__ void tos_interrupt_disable(uint32_t vector);
#endif /* _TOS_INTERRUPT_H_ */

View File

@@ -0,0 +1,25 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
#define __STUB__ __WEAK__
__STUB__ void chip_init(void)
{
}

View File

@@ -0,0 +1,286 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
__API__ uint32_t tos_cpu_clz(uint32_t val)
{
#if defined(TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT) && (TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT == 0u)
uint32_t nbr_lead_zeros = 0;
if (!(val & 0XFFFF0000)) {
val <<= 16;
nbr_lead_zeros += 16;
}
if (!(val & 0XFF000000)) {
val <<= 8;
nbr_lead_zeros += 8;
}
if (!(val & 0XF0000000)) {
val <<= 4;
nbr_lead_zeros += 4;
}
if (!(val & 0XC0000000)) {
val <<= 2;
nbr_lead_zeros += 2;
}
if (!(val & 0X80000000)) {
nbr_lead_zeros += 1;
}
if (!val) {
nbr_lead_zeros += 1;
}
return (nbr_lead_zeros);
#else
return port_clz(val);
#endif
}
__API__ void tos_cpu_int_disable(void)
{
port_int_disable();
}
__API__ void tos_cpu_int_enable(void)
{
port_int_enable();
}
__API__ cpu_cpsr_t tos_cpu_cpsr_save(void)
{
return port_cpsr_save();
}
__API__ void tos_cpu_cpsr_restore(cpu_cpsr_t cpsr)
{
port_cpsr_restore(cpsr);
}
__KERNEL__ void cpu_init(void)
{
k_cpu_cycle_per_tick = TOS_CFG_CPU_CLOCK / k_cpu_tick_per_second;
interrupt_init();
chip_init();
}
__KERNEL__ void cpu_reset(void)
{
port_cpu_reset();
}
__KERNEL__ void cpu_sched_start(void)
{
port_sched_start();
}
__KERNEL__ void cpu_context_switch(void)
{
port_context_switch();
}
__KERNEL__ void cpu_irq_context_switch(void)
{
port_irq_context_switch();
}
__KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick)
{
port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO);
port_systick_config(cycle_per_tick);
}
#if TOS_CFG_TICKLESS_EN > 0u
/**
* @brief Set value to systick reload value register
*
* @param cycles The value set to register
*
* @return None
*/
__STATIC_INLINE__ void cpu_systick_reload(k_cycle_t cycle_per_tick)
{
port_systick_reload(cycle_per_tick);
}
/**
* @brief Enable systick interrupt
*
* @return None
*/
__KERNEL__ void cpu_systick_resume(void)
{
port_systick_resume();
}
/**
* @brief Disable systick interrupt
*
* @return None
*/
__KERNEL__ void cpu_systick_suspend(void)
{
port_systick_suspend();
}
__KERNEL__ k_time_t cpu_systick_max_delay_millisecond(void)
{
return port_systick_max_delay_millisecond();
}
__KERNEL__ void cpu_systick_expires_set(k_time_t millisecond)
{
k_cycle_t cycles;
cycles = (k_cycle_t)((uint64_t)millisecond * TOS_CFG_CPU_CLOCK / K_TIME_MILLISEC_PER_SEC); /* CLOCK means cycle per second */
cpu_systick_reload(cycles - 12); /* interrupt delay */
}
__KERNEL__ void cpu_systick_pending_reset(void)
{
port_systick_pending_reset();
}
__KERNEL__ void cpu_systick_reset(void)
{
cpu_systick_reload(k_cpu_cycle_per_tick);
}
#endif /* TOS_CFG_TICKLESS_EN */
#if TOS_CFG_PWR_MGR_EN > 0u
__KERNEL__ void cpu_sleep_mode_enter(void)
{
port_sleep_mode_enter();
}
__KERNEL__ void cpu_stop_mode_enter(void)
{
port_stop_mode_enter();
}
__KERNEL__ void cpu_standby_mode_enter(void)
{
port_standby_mode_enter();
}
#endif /* TOS_CFG_PWR_MGR_EN */
__KERNEL__ k_stack_t *cpu_task_stk_init(void *entry,
void *arg,
void *exit,
k_stack_t *stk_base,
size_t stk_size)
{
cpu_data_t *sp;
cpu_context_t *context;
sp = (cpu_data_t *)&stk_base[stk_size];
sp = (cpu_data_t *)((cpu_addr_t)sp & 0xFFFFFFF8);
#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u
uint8_t *slot = (uint8_t *)&stk_base[0];
for (; slot < (uint8_t *)sp; ++slot) {
*slot = 0xCC;
}
#endif
context = (cpu_context_t *)sp;
--context;
#define CPSR_SVC_MODE 0x13
#define CPSR_BIT_T 0x20
/* we donnot set the irq bit, so first time context switch should enable irq */
context->cpsr = CPSR_SVC_MODE;
if ((cpu_addr_t)entry & 1) {
context->cpsr |= CPSR_BIT_T;
}
context->pc = (cpu_data_t)entry;
context->lr = (cpu_data_t)exit;
context->r12 = (cpu_data_t)0x12121212u;
context->r11 = (cpu_data_t)0x11111111u;
context->r10 = (cpu_data_t)0x10101010u;
context->r9 = (cpu_data_t)0x09090909u;
context->r8 = (cpu_data_t)0x08080808u;
context->r7 = (cpu_data_t)0x07070707u;
context->r6 = (cpu_data_t)0x06060606u;
context->r5 = (cpu_data_t)0x05050505u;
context->r4 = (cpu_data_t)0x04040404u;
context->r3 = (cpu_data_t)0x03030303u;
context->r2 = (cpu_data_t)0x02020202u;
context->r1 = (cpu_data_t)0x01010101u;
context->r0 = (cpu_data_t)arg;
return (k_stack_t *)context;
}
#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u
__KERNEL__ k_err_t cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth)
{
uint8_t *slot;
uint8_t *sp, *bp;
int the_depth = 0;
bp = (uint8_t *)&stk_base[0];
sp = &stk_base[stk_size];
sp = (uint8_t *)((cpu_addr_t)sp & 0xFFFFFFF8);
for (slot = sp - 1; slot >= bp; --slot) {
if (*slot != 0xCC) {
the_depth = sp - slot;
}
}
*depth = the_depth;
if (the_depth == stk_size) {
return K_ERR_TASK_STK_OVERFLOW;
}
return K_ERR_NONE;
}
#endif
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
__KERNEL__ void cpu_flush_fpu(void)
{
(void)__get_FPSCR();
}
#endif
__KERNEL__ void cpu_fault_diagnosis(void)
{
port_fault_diagnosis();
}
#endif /* TOS_CFG_FAULT_BACKTRACE_EN */

View File

@@ -0,0 +1,392 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
__STATIC_INLINE__ void fault_spin(void)
{
tos_knl_sched_lock();
tos_cpu_int_disable();
while (K_TRUE) {
;
}
}
/* EXC_RETURN:
31 - 28 : EXC_RETURN flag
27 - 5 : reserved
4 : 1, basic stack frame; 0, extended stack frame
3 : 1, return to Thread mode; 0, return to Handler mode
2 : 1, return to PSP; 0, return to MSP
1 : reserved, 0
0 : reserved, 1
*/
__STATIC_INLINE__ int fault_is_on_task(cpu_data_t lr)
{
return (lr & (1u << 2)) != 0;
}
__STATIC_INLINE__ int fault_is_thumb(cpu_data_t psr)
{
return (psr & (1u << 24)) != 0;
}
__STATIC_INLINE__ int fault_is_code(fault_info_t *info, cpu_data_t value)
{
return value >= info->code_start && value <= info->code_limit;
}
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
__STATIC_INLINE__ int fault_is_extended_stack_frame(cpu_data_t lr)
{
return (lr & (1u << 4)) == 0;
}
__STATIC__ void fault_dump_fpu_frame(fault_fpu_frame_t *fpu_frame)
{
/*
* As known, v7-m has a feature named "LAZY PUSH", for the reason we do not do any float
* operation in fault_backtrace, cpu will not do the real fpu register push to the stack.
* that means the value we dump in fault_dump_fpu_frame will not be the correct value of
* each FPU register.
* We define a function here which access to FPSCR, if this function involved, cpu will do
* the real FPU register push so we will get the correct dump.
* I know it's ugly, but it works. If you know a better way, please tell me.
*/
cpu_flush_fpu();
k_fault_log_writer("\n\n====================== FPU Registers =======================\n");
k_fault_log_writer(" %s: %08x\n", "FPSCR", fpu_frame->fpscr);
k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n",
"S0 ", fpu_frame->s0,
"S1 ", fpu_frame->s1,
"S2 ", fpu_frame->s2,
"S3 ", fpu_frame->s3);
k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n",
"S4 ", fpu_frame->s4,
"S5 ", fpu_frame->s5,
"S6 ", fpu_frame->s6,
"S7 ", fpu_frame->s7);
k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n",
"S8 ", fpu_frame->s8,
"S9 ", fpu_frame->s9,
"S10", fpu_frame->s10,
"S11", fpu_frame->s11);
k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n",
"S12", fpu_frame->s12,
"S13", fpu_frame->s13,
"S14", fpu_frame->s14,
"S15", fpu_frame->s15);
}
#endif
__STATIC__ void fault_dump_cpu_frame(fault_cpu_frame_t *cpu_frame)
{
k_fault_log_writer("\n\n====================== CPU Registers =======================\n");
k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n",
"R0 ", cpu_frame->r0,
"R1 ", cpu_frame->r1,
"R2 ", cpu_frame->r2,
"R3 ", cpu_frame->r3);
k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n",
"R12", cpu_frame->r12,
"LR ", cpu_frame->lr,
"PC ", cpu_frame->pc,
"PSR", cpu_frame->spsr);
}
__STATIC__ void fault_dump_stack(fault_info_t *info, size_t depth)
{
cpu_addr_t sp = info->sp_before_fault;;
k_fault_log_writer("\nTASK STACK DUMP:\n");
while (sp <= info->stack_limit && depth--) {
k_fault_log_writer(" addr: %08x data: %08x\n", sp, (cpu_data_t)*(cpu_data_t *)sp);
sp += sizeof(cpu_addr_t);
}
}
__STATIC__ void fault_call_stack_backtrace(fault_info_t *info, size_t depth)
{
cpu_data_t value;
cpu_addr_t sp = info->sp_before_fault;
if (info->is_stk_ovrf) {
return;
}
k_fault_log_writer("\n\n====================== Dump Call Stack =====================\n");
k_fault_log_writer(" %x\n", info->pc);
/* walk through the stack, check every content on stack whether is a instruction(code) */
for (; sp < info->stack_limit && depth; sp += sizeof(cpu_addr_t)) {
value = *((cpu_addr_t *)sp) - sizeof(cpu_addr_t);
/* if thumb, a instruction's first bit must be 1 */
if (info->is_thumb && !(value & 1)) {
continue;
}
if (fault_is_code(info, value)) {
k_fault_log_writer(" %x\n", value);
--depth;
}
}
}
__STATIC__ void fault_dump_task(fault_info_t *info)
{
k_task_t *task;
if (!info->is_on_task) {
return;
}
task = k_curr_task;
k_fault_log_writer("\n\n====================== Fault on task =======================\n");
k_fault_log_writer(" TASK NAME: %s\n", task->name);
k_fault_log_writer(" STK BASE: %x\n", info->stack_start);
k_fault_log_writer(" STK SIZE: %x\n", task->stk_size * sizeof(k_stack_t));
k_fault_log_writer(" STK LIMIT: %x\n", info->stack_limit);
if (!info->is_stk_ovrf) {
fault_dump_stack(info, K_FAULT_STACK_DUMP_DEPTH);
}
}
__STATIC__ void fault_dump_information(fault_info_t *info)
{
k_fault_log_writer("\n\n================== Dump Fault Information ==================\n");
k_fault_log_writer(" THUMB: %s\n", info->is_thumb ? "TRUE" : "FALSE");
k_fault_log_writer(" ON TASK: %s\n", info->is_on_task? "TRUE" : "FALSE");
k_fault_log_writer(" STK OVRF: %s\n", info->is_stk_ovrf? "TRUE" : "FALSE");
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
k_fault_log_writer(" EXT STK: %s\n", info->is_ext_stk_frm? "TRUE" : "FALSE");
#endif
k_fault_log_writer(" PC: %08x\n", info->pc);
k_fault_log_writer(" SP: %08x\n", info->sp_before_fault);
k_fault_log_writer(" STK START: %08x\n", info->stack_start);
k_fault_log_writer(" STK LIMIT: %08x\n", info->stack_limit);
k_fault_log_writer(" COD START: %08x\n", info->code_start);
k_fault_log_writer(" COD LIMIT: %08x\n", info->code_limit);
}
__STATIC__ void fault_gather_information(cpu_data_t lr, fault_exc_frame_t *frame, fault_info_t *info)
{
info->is_thumb = fault_is_thumb(frame->cpu_frame.spsr);
info->is_on_task = fault_is_on_task(lr);
info->pc = frame->cpu_frame.pc;
info->sp_before_fault = (cpu_addr_t)frame + sizeof(fault_cpu_frame_t);
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
info->is_ext_stk_frm = fault_is_extended_stack_frame(lr);
if (info->is_ext_stk_frm) {
info->sp_before_fault += sizeof(fault_fpu_frame_t);
}
#endif
info->code_start = fault_code_start();
info->code_limit = fault_code_limit();
if (info->is_on_task) {
info->stack_start = (cpu_addr_t)k_curr_task->stk_base;
info->stack_limit = info->stack_start + k_curr_task->stk_size * sizeof(k_task_t);
} else {
info->stack_start = fault_msp_start();
info->stack_limit = fault_msp_limit();
}
info->is_stk_ovrf = (info->sp_before_fault < info->stack_start || info->sp_before_fault > info->stack_limit);
}
__KERNEL__ int fault_default_log_writer(const char *format, ...)
{
int len;
va_list ap;
va_start(ap, format);
len = vprintf(format, ap);
va_end(ap);
return len;
}
__API__ void tos_fault_log_writer_set(k_fault_log_writer_t log_writer)
{
k_fault_log_writer = log_writer;
}
__KERNEL__ void fault_backtrace(cpu_addr_t lr, fault_exc_frame_t *frame)
{
fault_info_t info;
fault_gather_information(lr, frame, &info);
fault_dump_information(&info);
fault_dump_task(&info);
fault_dump_cpu_frame(&frame->cpu_frame);
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
if (info.is_ext_stk_frm) {
fault_dump_fpu_frame(&frame->fpu_frame);
}
#endif
fault_call_stack_backtrace(&info, K_FAULT_CALL_STACK_BACKTRACE_DEPTH);
cpu_fault_diagnosis();
fault_spin();
}
#endif
struct arm_iframe {
#if 0 // VFP
uint32_t fpexc;
#endif
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
uint32_t spsr;
};
struct arm_fault_frame {
#if 0 // VFP
uint32_t fpexc;
#endif
uint32_t r[13];
uint32_t lr;
uint32_t pc;
uint32_t spsr;
};
#define CPSR_MODE_MASK 0x1f
#define CPSR_MODE_USR 0x10
#define CPSR_MODE_FIQ 0x11
#define CPSR_MODE_IRQ 0x12
#define CPSR_MODE_SVC 0x13
#define CPSR_MODE_MON 0x16
#define CPSR_MODE_ABT 0x17
#define CPSR_MODE_UND 0x1b
#define CPSR_MODE_SYS 0x1f
static void dump_fault_frame(struct arm_fault_frame *frame)
{
printf("r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
printf("r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
printf("r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
printf("r12 0x%08x pc 0x%08x\n", frame->r[12], frame->pc);
printf("spsr 0x%08x\n", frame->spsr);
while (1);
}
static void dump_iframe(struct arm_iframe *frame)
{
printf("r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n", frame->r0, frame->r1, frame->r2, frame->r3);
printf("r12 0x%08x pc 0x%08x\n", frame->r12, frame->pc);
printf("spsr 0x%08x\n", frame->spsr);
}
static void exception_die_iframe(struct arm_iframe *frame, const char *msg)
{
printf("%s", msg);
dump_iframe(frame);
while (1);
}
void arm_undefined_handler(struct arm_iframe *frame)
{
printf("undefined\r\n");
/* look at the undefined instruction, figure out if it's something we can handle */
int in_thumb = frame->spsr & (1<<5);
if (in_thumb) {
frame->pc -= 2;
} else {
frame->pc -= 4;
}
uint32_t opcode = *(uint32_t *)frame->pc;
printf("undefined opcode 0x%x\n", opcode);
#if 0 // VFP
if (in_thumb) {
/* look for a 32bit thumb instruction */
if (opcode & 0x0000e800) {
/* swap the 16bit words */
opcode = (opcode >> 16) | (opcode << 16);
}
if (((opcode & 0xec000e00) == 0xec000a00) || // vfp
((opcode & 0xef000000) == 0xef000000) || // advanced simd data processing
((opcode & 0xff100000) == 0xf9000000)) { // VLD
//printf("vfp/neon thumb instruction 0x%08x at 0x%x\n", opcode, frame->pc);
goto fpu;
}
} else {
/* look for arm vfp/neon coprocessor instructions */
if (((opcode & 0x0c000e00) == 0x0c000a00) || // vfp
((opcode & 0xfe000000) == 0xf2000000) || // advanced simd data processing
((opcode & 0xff100000) == 0xf4000000)) { // VLD
//printf("vfp/neon arm instruction 0x%08x at 0x%x\n", opcode, frame->pc);
goto fpu;
}
}
#endif
exception_die_iframe(frame, "undefined abort, halting\n");
return;
#if 0 // VFP
fpu:
arm_fpu_undefined_instruction(frame);
#endif
}
void arm_data_abort_handler(struct arm_fault_frame *frame)
{
printf("data abort!!\r\n");
dump_fault_frame(frame);
}
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
{
printf("prefetch abort!!\r\n");
dump_fault_frame(frame);
}

View File

@@ -0,0 +1,150 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
__STATIC__ gic_data_t gic_data[GIC_NRS];
__STATIC_INLINE__ cpu_addr_t gic_base_get(void)
{
/* read CBAR */
return (ARM_MRC(15, 4, 15, 0, 0) & 0xFFFF0000UL);
}
__STATIC__ void gic_data_init(gic_data_t *gic)
{
cpu_addr_t gic_base;
gic_base = gic_base_get();
gic->dist = (gic_dist_t *)(gic_base + GICD_OFFSET); /* distributor */
gic->cpu = (gic_cpu_t *)(gic_base + GICC_OFFSET); /* cpu interface */
}
__STATIC__ void gic_dist_init(gic_dist_t *gic_dist)
{
uint32_t i = 0, int_id_max = 0;
// let's make it simple here, maybe SMP someday, but not now
#define IT_LINES_NUMBER(d_type) ((d_type) & 0x1FUL)
int_id_max = IT_LINES_NUMBER(gic_dist->D_TYPER) + 1;
/* Disable all PPI, SGI and SPI */
for (i = 0; i < int_id_max; ++i) {
gic_dist->D_ICENABLER[i] = 0xFFFFFFFFUL;
}
/* Enable group0 distribution */
gic_dist->D_CTLR = 1UL;
}
__STATIC__ void gic_cpu_init(gic_cpu_t *gic_cpu)
{
/* Make all interrupts have higher priority */
gic_cpu->C_PMR = (0xFFUL << (8 - GIC_PRIO_BITS)) & 0xFFUL;
/* No subpriority, all priority level allows preemption */
gic_cpu->C_BPR = 7 - GIC_PRIO_BITS;
/* Enable group0 signaling */
gic_cpu->C_CTLR = 1UL;
}
__STATIC_INLINE__ gic_data_t *gic_get(uint32_t gic_nr)
{
gic_data_t *gic;
if (gic_nr >= GIC_NRS) {
return K_NULL;
}
gic = &gic_data[gic_nr];
if (gic->cpu && gic->dist) {
return gic;
}
return K_NULL;
}
__KERNEL__ uint32_t gic_interrupt_id_get(uint32_t gic_nr)
{
gic_data_t *gic = gic_get(gic_nr);
if (gic) {
#define INTERRUPT_ID(iar) ((iar) & 0x3FFUL)
return INTERRUPT_ID(gic->cpu->C_IAR);
}
return (uint32_t)-1;
}
__KERNEL__ void gic_interrupt_end(uint32_t gic_nr, uint32_t vector)
{
gic_data_t *gic = gic_get(gic_nr);
if (gic) {
gic->cpu->C_EOIR = vector;
}
}
__KERNEL__ int gic_init(uint32_t gic_nr)
{
gic_data_t *gic;
if (gic_nr >= GIC_NRS) {
return -1;
}
gic = &gic_data[gic_nr];
gic_data_init(gic);
gic_dist_init(gic->dist);
gic_cpu_init(gic->cpu);
return 0;
}
__KERNEL__ void gic_interrupt_enable(uint32_t gic_nr, uint32_t vector)
{
int reg;
uint32_t mask;
gic_data_t *gic;
gic = gic_get(gic_nr);
if (gic) {
reg = vector / 32;
mask = 1ULL << (vector % 32);
gic->dist->D_ISENABLER[reg] = mask;
}
}
__KERNEL__ void gic_interrupt_disable(uint32_t gic_nr, uint32_t vector)
{
int reg;
uint32_t mask;
gic_data_t *gic;
gic = gic_get(gic_nr);
if (gic) {
reg = vector / 32;
mask = 1ULL << (vector % 32);
gic->dist->D_ICENABLER[reg] = mask;
}
}

View File

@@ -0,0 +1,67 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
__STATIC__ int_handle_t int_handle_table[INTERRUPT_MAX];
__KERNEL__ void interrupt_irq(int_frame_t *int_frame)
{
uint32_t vector;
int_handle_t *handle;
vector = gic_interrupt_id_get(0u);
if (vector > INTERRUPT_MAX || vector == (uint32_t)-1) {
return;
}
handle = &int_handle_table[vector];
if (handle->handler) {
handle->handler(handle->arg);
}
gic_interrupt_end(0u, vector);
}
__KERNEL__ int interrupt_init(void)
{
gic_init(0u);
return 0;
}
__API__ int tos_interrupt_handler_register(uint32_t vector, int_handler_t handler, void *arg)
{
if (vector < INTERRUPT_MAX) {
int_handle_table[vector].handler = handler;
int_handle_table[vector].arg = arg;
return 0;
}
return -1;
}
__API__ void tos_interrupt_enable(uint32_t vector)
{
gic_interrupt_enable(0u, vector);
}
__API__ void tos_interrupt_disable(uint32_t vector)
{
gic_interrupt_disable(0u, vector);
}

View File

@@ -0,0 +1,62 @@
#include "tos_k.h"
#include "imx6ul.h"
/* set the core clock to 528MHz */
void clock_init(void)
{
unsigned int reg = 0;
if ((((CCM->CCSR) >> 2) & 0x1) == 0) {
CCM->CCSR &= ~(1 << 8);
CCM->CCSR |= (1 << 2);
}
CCM_ANALOG->PLL_ARM = (1 << 13) | ((88 << 0) & 0X7F);
CCM->CCSR &= ~(1 << 2);
CCM->CACRR = 1;
reg = CCM_ANALOG->PFD_528;
reg &= ~(0X3F3F3F3F);
reg |= 32 << 24;
reg |= 24 << 16;
reg |= 16 << 8;
reg |= 27 << 0;
CCM_ANALOG->PFD_528 = reg;
reg = 0;
reg = CCM_ANALOG->PFD_480;
reg &= ~(0X3F3F3F3F);
reg |= 19 << 24;
reg |= 17 << 16;
reg |= 16 << 8;
reg |= 12 << 0;
CCM_ANALOG->PFD_480 = reg;
CCM->CBCMR &= ~(3 << 18);
CCM->CBCMR |= (1 << 18);
CCM->CBCDR &= ~(1 << 25);
while(CCM->CDHIPR & (1 << 5)) {
;
}
CCM->CBCDR &= ~(3 << 8);
CCM->CBCDR |= 1 << 8;
CCM->CSCMR1 &= ~(1 << 6);
CCM->CSCMR1 &= ~(7 << 0);
CCM->CSCDR1 &= ~(1 << 6);
CCM->CSCDR1 &= ~0X3F;
}
void clock_enable(void)
{
CCM->CCGR0 = 0XFFFFFFFF;
CCM->CCGR1 = 0XFFFFFFFF;
CCM->CCGR2 = 0XFFFFFFFF;
CCM->CCGR3 = 0XFFFFFFFF;
CCM->CCGR4 = 0XFFFFFFFF;
CCM->CCGR5 = 0XFFFFFFFF;
CCM->CCGR6 = 0XFFFFFFFF;
}

View File

@@ -0,0 +1,27 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
#include "imx6ul.h"
__KERNEL__ void chip_init(void)
{
clock_init();
clock_enable();
systick_init(k_cpu_tick_per_second);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _PLATFORM_H_
#define _PLATFORM_H_
#define INTERRUPT_MAX 128
#define KERNEL_BASE 0X87800000
#endif /* _CHIP_H_ */

View File

@@ -0,0 +1,27 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _GIC_H_
#define _GIC_H_
#define GICD_OFFSET 0x1000
#define GICC_OFFSET 0x2000
#define GIC_PRIO_BITS 5 /**< Number of Bits used for Priority Levels */
#define GIC_NRS 1 /**< how many gic on this chip? */
#endif /* _GIC_H_ */

View File

@@ -0,0 +1,25 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _CLOCK_H_
#define _CLOCK_H_
void clock_init(void);
void clock_enable(void);
#endif

View File

@@ -0,0 +1,723 @@
#ifndef __CORTEX_CA7_H
#define __CORTEX_CA7_H
#include <stdint.h>
#include <string.h>
#define FORCEDINLINE __attribute__((always_inline))
#define __ASM __asm /* GNU C语言内嵌汇编关键字 */
#define __INLINE inline /* GNU内联关键字 */
#define __STATIC_INLINE static inline
#define __IM volatile const /* 只读 */
#define __OM volatile /* 只写 */
#define __IOM volatile /* 读写 */
#define __STRINGIFY(x) #x
/* C语言实现MCR指令 */
#define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \
__ASM volatile ("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: : "r" (src) )
/* C语言实现MRC指令 */
#define __MRC(coproc, opcode_1, CRn, CRm, opcode_2) \
({ \
uint32_t __dst; \
__ASM volatile ("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: "=r" (__dst) ); \
__dst; \
})
/* 其他一些C语言内嵌汇编 */
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_APSR(uint32_t apsr)
{
__ASM volatile ("MSR apsr, %0" : : "r" (apsr) : "cc");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, cpsr" : "=r" (result) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
{
__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPEXC(void)
{
uint32_t result;
__ASM volatile ("VMRS %0, fpexc" : "=r" (result) );
return result;
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
{
__ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc));
}
/*******************************************************************************
* 一些内核寄存器定义和抽象
定义如下几个内核寄存器:
- CPSR
- CP15
******************************************************************************/
/* CPSR寄存器
* 参考资料ARM Cortex-A(armV7)编程手册V4.0.pdf P46
*/
typedef union
{
struct
{
uint32_t M:5; /*!< bit: 0.. 4 Mode field */
uint32_t T:1; /*!< bit: 5 Thumb execution state bit */
uint32_t F:1; /*!< bit: 6 FIQ mask bit */
uint32_t I:1; /*!< bit: 7 IRQ mask bit */
uint32_t A:1; /*!< bit: 8 Asynchronous abort mask bit */
uint32_t E:1; /*!< bit: 9 Endianness execution state bit */
uint32_t IT1:6; /*!< bit: 10..15 If-Then execution state bits 2-7 */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved0:4; /*!< bit: 20..23 Reserved */
uint32_t J:1; /*!< bit: 24 Jazelle bit */
uint32_t IT0:2; /*!< bit: 25..26 If-Then execution state bits 0-1 */
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 */
} CPSR_Type;
/* CP15的SCTLR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P105
*/
typedef union
{
struct
{
uint32_t M:1; /*!< bit: 0 MMU enable */
uint32_t A:1; /*!< bit: 1 Alignment check enable */
uint32_t C:1; /*!< bit: 2 Cache enable */
uint32_t _reserved0:2; /*!< bit: 3.. 4 Reserved */
uint32_t CP15BEN:1; /*!< bit: 5 CP15 barrier enable */
uint32_t _reserved1:1; /*!< bit: 6 Reserved */
uint32_t B:1; /*!< bit: 7 Endianness model */
uint32_t _reserved2:2; /*!< bit: 8.. 9 Reserved */
uint32_t SW:1; /*!< bit: 10 SWP and SWPB enable */
uint32_t Z:1; /*!< bit: 11 Branch prediction enable */
uint32_t I:1; /*!< bit: 12 Instruction cache enable */
uint32_t V:1; /*!< bit: 13 Vectors bit */
uint32_t RR:1; /*!< bit: 14 Round Robin select */
uint32_t _reserved3:2; /*!< bit:15..16 Reserved */
uint32_t HA:1; /*!< bit: 17 Hardware Access flag enable */
uint32_t _reserved4:1; /*!< bit: 18 Reserved */
uint32_t WXN:1; /*!< bit: 19 Write permission implies XN */
uint32_t UWXN:1; /*!< bit: 20 Unprivileged write permission implies PL1 XN */
uint32_t FI:1; /*!< bit: 21 Fast interrupts configuration enable */
uint32_t U:1; /*!< bit: 22 Alignment model */
uint32_t _reserved5:1; /*!< bit: 23 Reserved */
uint32_t VE:1; /*!< bit: 24 Interrupt Vectors Enable */
uint32_t EE:1; /*!< bit: 25 Exception Endianness */
uint32_t _reserved6:1; /*!< bit: 26 Reserved */
uint32_t NMFI:1; /*!< bit: 27 Non-maskable FIQ (NMFI) support */
uint32_t TRE:1; /*!< bit: 28 TEX remap enable. */
uint32_t AFE:1; /*!< bit: 29 Access flag enable */
uint32_t TE:1; /*!< bit: 30 Thumb Exception enable */
uint32_t _reserved7:1; /*!< bit: 31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} SCTLR_Type;
/* CP15 寄存器SCTLR各个位定义 */
#define SCTLR_TE_Pos 30U /*!< SCTLR: TE Position */
#define SCTLR_TE_Msk (1UL << SCTLR_TE_Pos) /*!< SCTLR: TE Mask */
#define SCTLR_AFE_Pos 29U /*!< SCTLR: AFE Position */
#define SCTLR_AFE_Msk (1UL << SCTLR_AFE_Pos) /*!< SCTLR: AFE Mask */
#define SCTLR_TRE_Pos 28U /*!< SCTLR: TRE Position */
#define SCTLR_TRE_Msk (1UL << SCTLR_TRE_Pos) /*!< SCTLR: TRE Mask */
#define SCTLR_NMFI_Pos 27U /*!< SCTLR: NMFI Position */
#define SCTLR_NMFI_Msk (1UL << SCTLR_NMFI_Pos) /*!< SCTLR: NMFI Mask */
#define SCTLR_EE_Pos 25U /*!< SCTLR: EE Position */
#define SCTLR_EE_Msk (1UL << SCTLR_EE_Pos) /*!< SCTLR: EE Mask */
#define SCTLR_VE_Pos 24U /*!< SCTLR: VE Position */
#define SCTLR_VE_Msk (1UL << SCTLR_VE_Pos) /*!< SCTLR: VE Mask */
#define SCTLR_U_Pos 22U /*!< SCTLR: U Position */
#define SCTLR_U_Msk (1UL << SCTLR_U_Pos) /*!< SCTLR: U Mask */
#define SCTLR_FI_Pos 21U /*!< SCTLR: FI Position */
#define SCTLR_FI_Msk (1UL << SCTLR_FI_Pos) /*!< SCTLR: FI Mask */
#define SCTLR_UWXN_Pos 20U /*!< SCTLR: UWXN Position */
#define SCTLR_UWXN_Msk (1UL << SCTLR_UWXN_Pos) /*!< SCTLR: UWXN Mask */
#define SCTLR_WXN_Pos 19U /*!< SCTLR: WXN Position */
#define SCTLR_WXN_Msk (1UL << SCTLR_WXN_Pos) /*!< SCTLR: WXN Mask */
#define SCTLR_HA_Pos 17U /*!< SCTLR: HA Position */
#define SCTLR_HA_Msk (1UL << SCTLR_HA_Pos) /*!< SCTLR: HA Mask */
#define SCTLR_RR_Pos 14U /*!< SCTLR: RR Position */
#define SCTLR_RR_Msk (1UL << SCTLR_RR_Pos) /*!< SCTLR: RR Mask */
#define SCTLR_V_Pos 13U /*!< SCTLR: V Position */
#define SCTLR_V_Msk (1UL << SCTLR_V_Pos) /*!< SCTLR: V Mask */
#define SCTLR_I_Pos 12U /*!< SCTLR: I Position */
#define SCTLR_I_Msk (1UL << SCTLR_I_Pos) /*!< SCTLR: I Mask */
#define SCTLR_Z_Pos 11U /*!< SCTLR: Z Position */
#define SCTLR_Z_Msk (1UL << SCTLR_Z_Pos) /*!< SCTLR: Z Mask */
#define SCTLR_SW_Pos 10U /*!< SCTLR: SW Position */
#define SCTLR_SW_Msk (1UL << SCTLR_SW_Pos) /*!< SCTLR: SW Mask */
#define SCTLR_B_Pos 7U /*!< SCTLR: B Position */
#define SCTLR_B_Msk (1UL << SCTLR_B_Pos) /*!< SCTLR: B Mask */
#define SCTLR_CP15BEN_Pos 5U /*!< SCTLR: CP15BEN Position */
#define SCTLR_CP15BEN_Msk (1UL << SCTLR_CP15BEN_Pos) /*!< SCTLR: CP15BEN Mask */
#define SCTLR_C_Pos 2U /*!< SCTLR: C Position */
#define SCTLR_C_Msk (1UL << SCTLR_C_Pos) /*!< SCTLR: C Mask */
#define SCTLR_A_Pos 1U /*!< SCTLR: A Position */
#define SCTLR_A_Msk (1UL << SCTLR_A_Pos) /*!< SCTLR: A Mask */
#define SCTLR_M_Pos 0U /*!< SCTLR: M Position */
#define SCTLR_M_Msk (1UL << SCTLR_M_Pos) /*!< SCTLR: M Mask */
/* CP15的ACTLR寄存器
* 参考资料:Cortex-A7 Technical ReferenceManua.pdf P113
*/
typedef union
{
struct
{
uint32_t _reserved0:6; /*!< bit: 0.. 5 Reserved */
uint32_t SMP:1; /*!< bit: 6 Enables coherent requests to the processor */
uint32_t _reserved1:3; /*!< bit: 7.. 9 Reserved */
uint32_t DODMBS:1; /*!< bit: 10 Disable optimized data memory barrier behavior */
uint32_t L2RADIS:1; /*!< bit: 11 L2 Data Cache read-allocate mode disable */
uint32_t L1RADIS:1; /*!< bit: 12 L1 Data Cache read-allocate mode disable */
uint32_t L1PCTL:2; /*!< bit:13..14 L1 Data prefetch control */
uint32_t DDVM:1; /*!< bit: 15 Disable Distributed Virtual Memory (DVM) transactions */
uint32_t _reserved3:12; /*!< bit:16..27 Reserved */
uint32_t DDI:1; /*!< bit: 28 Disable dual issue */
uint32_t _reserved7:3; /*!< bit:29..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} ACTLR_Type;
#define ACTLR_DDI_Pos 28U /*!< ACTLR: DDI Position */
#define ACTLR_DDI_Msk (1UL << ACTLR_DDI_Pos) /*!< ACTLR: DDI Mask */
#define ACTLR_DDVM_Pos 15U /*!< ACTLR: DDVM Position */
#define ACTLR_DDVM_Msk (1UL << ACTLR_DDVM_Pos) /*!< ACTLR: DDVM Mask */
#define ACTLR_L1PCTL_Pos 13U /*!< ACTLR: L1PCTL Position */
#define ACTLR_L1PCTL_Msk (3UL << ACTLR_L1PCTL_Pos) /*!< ACTLR: L1PCTL Mask */
#define ACTLR_L1RADIS_Pos 12U /*!< ACTLR: L1RADIS Position */
#define ACTLR_L1RADIS_Msk (1UL << ACTLR_L1RADIS_Pos) /*!< ACTLR: L1RADIS Mask */
#define ACTLR_L2RADIS_Pos 11U /*!< ACTLR: L2RADIS Position */
#define ACTLR_L2RADIS_Msk (1UL << ACTLR_L2RADIS_Pos) /*!< ACTLR: L2RADIS Mask */
#define ACTLR_DODMBS_Pos 10U /*!< ACTLR: DODMBS Position */
#define ACTLR_DODMBS_Msk (1UL << ACTLR_DODMBS_Pos) /*!< ACTLR: DODMBS Mask */
#define ACTLR_SMP_Pos 6U /*!< ACTLR: SMP Position */
#define ACTLR_SMP_Msk (1UL << ACTLR_SMP_Pos) /*!< ACTLR: SMP Mask */
/* CP15的CPACR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P115
*/
typedef union
{
struct
{
uint32_t _reserved0:20; /*!< bit: 0..19 Reserved */
uint32_t cp10:2; /*!< bit:20..21 Access rights for coprocessor 10 */
uint32_t cp11:2; /*!< bit:22..23 Access rights for coprocessor 11 */
uint32_t _reserved1:6; /*!< bit:24..29 Reserved */
uint32_t D32DIS:1; /*!< bit: 30 Disable use of registers D16-D31 of the VFP register file */
uint32_t ASEDIS:1; /*!< bit: 31 Disable Advanced SIMD Functionality */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CPACR_Type;
#define CPACR_ASEDIS_Pos 31U /*!< CPACR: ASEDIS Position */
#define CPACR_ASEDIS_Msk (1UL << CPACR_ASEDIS_Pos) /*!< CPACR: ASEDIS Mask */
#define CPACR_D32DIS_Pos 30U /*!< CPACR: D32DIS Position */
#define CPACR_D32DIS_Msk (1UL << CPACR_D32DIS_Pos) /*!< CPACR: D32DIS Mask */
#define CPACR_cp11_Pos 22U /*!< CPACR: cp11 Position */
#define CPACR_cp11_Msk (3UL << CPACR_cp11_Pos) /*!< CPACR: cp11 Mask */
#define CPACR_cp10_Pos 20U /*!< CPACR: cp10 Position */
#define CPACR_cp10_Msk (3UL << CPACR_cp10_Pos) /*!< CPACR: cp10 Mask */
/* CP15的DFSR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P128
*/
typedef union
{
struct
{
uint32_t FS0:4; /*!< bit: 0.. 3 Fault Status bits bit 0-3 */
uint32_t Domain:4; /*!< bit: 4.. 7 Fault on which domain */
uint32_t _reserved0:2; /*!< bit: 8.. 9 Reserved */
uint32_t FS1:1; /*!< bit: 10 Fault Status bits bit 4 */
uint32_t WnR:1; /*!< bit: 11 Write not Read bit */
uint32_t ExT:1; /*!< bit: 12 External abort type */
uint32_t CM:1; /*!< bit: 13 Cache maintenance fault */
uint32_t _reserved1:18; /*!< bit:14..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} DFSR_Type;
#define DFSR_CM_Pos 13U /*!< DFSR: CM Position */
#define DFSR_CM_Msk (1UL << DFSR_CM_Pos) /*!< DFSR: CM Mask */
#define DFSR_Ext_Pos 12U /*!< DFSR: Ext Position */
#define DFSR_Ext_Msk (1UL << DFSR_Ext_Pos) /*!< DFSR: Ext Mask */
#define DFSR_WnR_Pos 11U /*!< DFSR: WnR Position */
#define DFSR_WnR_Msk (1UL << DFSR_WnR_Pos) /*!< DFSR: WnR Mask */
#define DFSR_FS1_Pos 10U /*!< DFSR: FS1 Position */
#define DFSR_FS1_Msk (1UL << DFSR_FS1_Pos) /*!< DFSR: FS1 Mask */
#define DFSR_Domain_Pos 4U /*!< DFSR: Domain Position */
#define DFSR_Domain_Msk (0xFUL << DFSR_Domain_Pos) /*!< DFSR: Domain Mask */
#define DFSR_FS0_Pos 0U /*!< DFSR: FS0 Position */
#define DFSR_FS0_Msk (0xFUL << DFSR_FS0_Pos) /*!< DFSR: FS0 Mask */
/* CP15的IFSR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P131
*/
typedef union
{
struct
{
uint32_t FS0:4; /*!< bit: 0.. 3 Fault Status bits bit 0-3 */
uint32_t _reserved0:6; /*!< bit: 4.. 9 Reserved */
uint32_t FS1:1; /*!< bit: 10 Fault Status bits bit 4 */
uint32_t _reserved1:1; /*!< bit: 11 Reserved */
uint32_t ExT:1; /*!< bit: 12 External abort type */
uint32_t _reserved2:19; /*!< bit:13..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IFSR_Type;
#define IFSR_ExT_Pos 12U /*!< IFSR: ExT Position */
#define IFSR_ExT_Msk (1UL << IFSR_ExT_Pos) /*!< IFSR: ExT Mask */
#define IFSR_FS1_Pos 10U /*!< IFSR: FS1 Position */
#define IFSR_FS1_Msk (1UL << IFSR_FS1_Pos) /*!< IFSR: FS1 Mask */
#define IFSR_FS0_Pos 0U /*!< IFSR: FS0 Position */
#define IFSR_FS0_Msk (0xFUL << IFSR_FS0_Pos) /*!< IFSR: FS0 Mask */
/* CP15的ISR寄存器
* 参考资料ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf P1640
*/
typedef union
{
struct
{
uint32_t _reserved0:6; /*!< bit: 0.. 5 Reserved */
uint32_t F:1; /*!< bit: 6 FIQ pending bit */
uint32_t I:1; /*!< bit: 7 IRQ pending bit */
uint32_t A:1; /*!< bit: 8 External abort pending bit */
uint32_t _reserved1:23; /*!< bit:14..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} ISR_Type;
#define ISR_A_Pos 13U /*!< ISR: A Position */
#define ISR_A_Msk (1UL << ISR_A_Pos) /*!< ISR: A Mask */
#define ISR_I_Pos 12U /*!< ISR: I Position */
#define ISR_I_Msk (1UL << ISR_I_Pos) /*!< ISR: I Mask */
#define ISR_F_Pos 11U /*!< ISR: F Position */
#define ISR_F_Msk (1UL << ISR_F_Pos) /*!< ISR: F Mask */
/* Mask and shift a bit field value for use in a register bit range. */
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
/* Mask and shift a register value to extract a bit filed value. */
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
/*******************************************************************************
* CP15 访问函数
******************************************************************************/
FORCEDINLINE __STATIC_INLINE uint32_t __get_SCTLR(void)
{
return __MRC(15, 0, 1, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{
__MCR(15, 0, sctlr, 1, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_ACTLR(void)
{
return __MRC(15, 0, 1, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_ACTLR(uint32_t actlr)
{
__MCR(15, 0, actlr, 1, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_CPACR(void)
{
return __MRC(15, 0, 1, 0, 2);
}
FORCEDINLINE __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{
__MCR(15, 0, cpacr, 1, 0, 2);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_TTBR0(void)
{
return __MRC(15, 0, 2, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_TTBR0(uint32_t ttbr0)
{
__MCR(15, 0, ttbr0, 2, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_TTBR1(void)
{
return __MRC(15, 0, 2, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_TTBR1(uint32_t ttbr1)
{
__MCR(15, 0, ttbr1, 2, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_TTBCR(void)
{
return __MRC(15, 0, 2, 0, 2);
}
FORCEDINLINE __STATIC_INLINE void __set_TTBCR(uint32_t ttbcr)
{
__MCR(15, 0, ttbcr, 2, 0, 2);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_DACR(void)
{
return __MRC(15, 0, 3, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_DACR(uint32_t dacr)
{
__MCR(15, 0, dacr, 3, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_DFSR(void)
{
return __MRC(15, 0, 5, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_DFSR(uint32_t dfsr)
{
__MCR(15, 0, dfsr, 5, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_IFSR(void)
{
return __MRC(15, 0, 5, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_IFSR(uint32_t ifsr)
{
__MCR(15, 0, ifsr, 5, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_DFAR(void)
{
return __MRC(15, 0, 6, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_DFAR(uint32_t dfar)
{
__MCR(15, 0, dfar, 6, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_IFAR(void)
{
return __MRC(15, 0, 6, 0, 2);
}
FORCEDINLINE __STATIC_INLINE void __set_IFAR(uint32_t ifar)
{
__MCR(15, 0, ifar, 6, 0, 2);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_VBAR(void)
{
return __MRC(15, 0, 12, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_VBAR(uint32_t vbar)
{
__MCR(15, 0, vbar, 12, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_ISR(void)
{
return __MRC(15, 0, 12, 1, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_ISR(uint32_t isr)
{
__MCR(15, 0, isr, 12, 1, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_CONTEXTIDR(void)
{
return __MRC(15, 0, 13, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_CONTEXTIDR(uint32_t contextidr)
{
__MCR(15, 0, contextidr, 13, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_CBAR(void)
{
return __MRC(15, 4, 15, 0, 0);
}
/*******************************************************************************
* GIC相关内容
*有关GIC的内容参考ARM Generic Interrupt Controller(ARM GIC控制器)V2.0.pdf
******************************************************************************/
/*
* GIC寄存器描述结构体
* GIC分为分发器端和CPU接口端
*/
typedef struct
{
uint32_t RESERVED0[1024];
__IOM uint32_t D_CTLR; /*!< Offset: 0x1000 (R/W) Distributor Control Register */
__IM uint32_t D_TYPER; /*!< Offset: 0x1004 (R/ ) Interrupt Controller Type Register */
__IM uint32_t D_IIDR; /*!< Offset: 0x1008 (R/ ) Distributor Implementer Identification Register */
uint32_t RESERVED1[29];
__IOM uint32_t D_IGROUPR[16]; /*!< Offset: 0x1080 - 0x0BC (R/W) Interrupt Group Registers */
uint32_t RESERVED2[16];
__IOM uint32_t D_ISENABLER[16]; /*!< Offset: 0x1100 - 0x13C (R/W) Interrupt Set-Enable Registers */
uint32_t RESERVED3[16];
__IOM uint32_t D_ICENABLER[16]; /*!< Offset: 0x1180 - 0x1BC (R/W) Interrupt Clear-Enable Registers */
uint32_t RESERVED4[16];
__IOM uint32_t D_ISPENDR[16]; /*!< Offset: 0x1200 - 0x23C (R/W) Interrupt Set-Pending Registers */
uint32_t RESERVED5[16];
__IOM uint32_t D_ICPENDR[16]; /*!< Offset: 0x1280 - 0x2BC (R/W) Interrupt Clear-Pending Registers */
uint32_t RESERVED6[16];
__IOM uint32_t D_ISACTIVER[16]; /*!< Offset: 0x1300 - 0x33C (R/W) Interrupt Set-Active Registers */
uint32_t RESERVED7[16];
__IOM uint32_t D_ICACTIVER[16]; /*!< Offset: 0x1380 - 0x3BC (R/W) Interrupt Clear-Active Registers */
uint32_t RESERVED8[16];
__IOM uint8_t D_IPRIORITYR[512]; /*!< Offset: 0x1400 - 0x5FC (R/W) Interrupt Priority Registers */
uint32_t RESERVED9[128];
__IOM uint8_t D_ITARGETSR[512]; /*!< Offset: 0x1800 - 0x9FC (R/W) Interrupt Targets Registers */
uint32_t RESERVED10[128];
__IOM uint32_t D_ICFGR[32]; /*!< Offset: 0x1C00 - 0xC7C (R/W) Interrupt configuration registers */
uint32_t RESERVED11[32];
__IM uint32_t D_PPISR; /*!< Offset: 0x1D00 (R/ ) Private Peripheral Interrupt Status Register */
__IM uint32_t D_SPISR[15]; /*!< Offset: 0x1D04 - 0xD3C (R/ ) Shared Peripheral Interrupt Status Registers */
uint32_t RESERVED12[112];
__OM uint32_t D_SGIR; /*!< Offset: 0x1F00 ( /W) Software Generated Interrupt Register */
uint32_t RESERVED13[3];
__IOM uint8_t D_CPENDSGIR[16]; /*!< Offset: 0x1F10 - 0xF1C (R/W) SGI Clear-Pending Registers */
__IOM uint8_t D_SPENDSGIR[16]; /*!< Offset: 0x1F20 - 0xF2C (R/W) SGI Set-Pending Registers */
uint32_t RESERVED14[40];
__IM uint32_t D_PIDR4; /*!< Offset: 0x1FD0 (R/ ) Peripheral ID4 Register */
__IM uint32_t D_PIDR5; /*!< Offset: 0x1FD4 (R/ ) Peripheral ID5 Register */
__IM uint32_t D_PIDR6; /*!< Offset: 0x1FD8 (R/ ) Peripheral ID6 Register */
__IM uint32_t D_PIDR7; /*!< Offset: 0x1FDC (R/ ) Peripheral ID7 Register */
__IM uint32_t D_PIDR0; /*!< Offset: 0x1FE0 (R/ ) Peripheral ID0 Register */
__IM uint32_t D_PIDR1; /*!< Offset: 0x1FE4 (R/ ) Peripheral ID1 Register */
__IM uint32_t D_PIDR2; /*!< Offset: 0x1FE8 (R/ ) Peripheral ID2 Register */
__IM uint32_t D_PIDR3; /*!< Offset: 0x1FEC (R/ ) Peripheral ID3 Register */
__IM uint32_t D_CIDR0; /*!< Offset: 0x1FF0 (R/ ) Component ID0 Register */
__IM uint32_t D_CIDR1; /*!< Offset: 0x1FF4 (R/ ) Component ID1 Register */
__IM uint32_t D_CIDR2; /*!< Offset: 0x1FF8 (R/ ) Component ID2 Register */
__IM uint32_t D_CIDR3; /*!< Offset: 0x1FFC (R/ ) Component ID3 Register */
__IOM uint32_t C_CTLR; /*!< Offset: 0x2000 (R/W) CPU Interface Control Register */
__IOM uint32_t C_PMR; /*!< Offset: 0x2004 (R/W) Interrupt Priority Mask Register */
__IOM uint32_t C_BPR; /*!< Offset: 0x2008 (R/W) Binary Point Register */
__IM uint32_t C_IAR; /*!< Offset: 0x200C (R/ ) Interrupt Acknowledge Register */
__OM uint32_t C_EOIR; /*!< Offset: 0x2010 ( /W) End Of Interrupt Register */
__IM uint32_t C_RPR; /*!< Offset: 0x2014 (R/ ) Running Priority Register */
__IM uint32_t C_HPPIR; /*!< Offset: 0x2018 (R/ ) Highest Priority Pending Interrupt Register */
__IOM uint32_t C_ABPR; /*!< Offset: 0x201C (R/W) Aliased Binary Point Register */
__IM uint32_t C_AIAR; /*!< Offset: 0x2020 (R/ ) Aliased Interrupt Acknowledge Register */
__OM uint32_t C_AEOIR; /*!< Offset: 0x2024 ( /W) Aliased End Of Interrupt Register */
__IM uint32_t C_AHPPIR; /*!< Offset: 0x2028 (R/ ) Aliased Highest Priority Pending Interrupt Register */
uint32_t RESERVED15[41];
__IOM uint32_t C_APR0; /*!< Offset: 0x20D0 (R/W) Active Priority Register */
uint32_t RESERVED16[3];
__IOM uint32_t C_NSAPR0; /*!< Offset: 0x20E0 (R/W) Non-secure Active Priority Register */
uint32_t RESERVED17[6];
__IM uint32_t C_IIDR; /*!< Offset: 0x20FC (R/ ) CPU Interface Identification Register */
uint32_t RESERVED18[960];
__OM uint32_t C_DIR; /*!< Offset: 0x3000 ( /W) Deactivate Interrupt Register */
} GIC_Type;
/*
* GIC初始化
* 为了简单使用GIC的group0
*/
FORCEDINLINE __STATIC_INLINE void GIC_Init(void)
{
uint32_t i;
uint32_t irqRegs;
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
irqRegs = (gic->D_TYPER & 0x1FUL) + 1;
/* On POR, all SPI is in group 0, level-sensitive and using 1-N model */
/* Disable all PPI, SGI and SPI */
for (i = 0; i < irqRegs; i++)
gic->D_ICENABLER[i] = 0xFFFFFFFFUL;
/* Make all interrupts have higher priority */
gic->C_PMR = (0xFFUL << (8 - __GIC_PRIO_BITS)) & 0xFFUL;
/* No subpriority, all priority level allows preemption */
gic->C_BPR = 7 - __GIC_PRIO_BITS;
/* Enable group0 distribution */
gic->D_CTLR = 1UL;
/* Enable group0 signaling */
gic->C_CTLR = 1UL;
}
/*
* 使能指定的中断
*/
FORCEDINLINE __STATIC_INLINE void GIC_EnableIRQ(IRQn_Type IRQn)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->D_ISENABLER[((uint32_t)(int32_t)IRQn) >> 5] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/*
* 关闭指定的中断
*/
FORCEDINLINE __STATIC_INLINE void GIC_DisableIRQ(IRQn_Type IRQn)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->D_ICENABLER[((uint32_t)(int32_t)IRQn) >> 5] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/*
* 返回中断号
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_AcknowledgeIRQ(void)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return gic->C_IAR & 0x1FFFUL;
}
/*
* 向EOIR写入发送中断的中断号来释放中断
*/
FORCEDINLINE __STATIC_INLINE void GIC_DeactivateIRQ(uint32_t value)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->C_EOIR = value;
}
/*
* 获取运行优先级
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_GetRunningPriority(void)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return gic->C_RPR & 0xFFUL;
}
/*
* 设置组优先级
*/
FORCEDINLINE __STATIC_INLINE void GIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->C_BPR = PriorityGroup & 0x7UL;
}
/*
* 获取组优先级
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_GetPriorityGrouping(void)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return gic->C_BPR & 0x7UL;
}
/*
* 设置优先级
*/
FORCEDINLINE __STATIC_INLINE void GIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->D_IPRIORITYR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8UL - __GIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
/*
* 获取优先级
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_GetPriority(IRQn_Type IRQn)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return(((uint32_t)gic->D_IPRIORITYR[((uint32_t)(int32_t)IRQn)] >> (8UL - __GIC_PRIO_BITS)));
}
#endif

View File

@@ -0,0 +1,28 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _IMX6UL_H_
#define _IMX6UL_H_
#include "MCIMX6Y2.h"
#include "core_ca7.h"
#include "clock.h"
#include "systick.h"
#endif /* _IMX6UL_H_ */

View File

@@ -0,0 +1,7 @@
#ifndef _SYSTICK_H_
#define _SYSTICK_H_
void systick_init(k_tick_t tick_per_second);
#endif /* _SYSTICK_H_ */

View File

@@ -0,0 +1,37 @@
#include "tos_k.h"
#include "imx6ul.h"
static void epit1_init(unsigned int frac, unsigned int value)
{
if (frac > 0XFFF) {
frac = 0XFFF;
}
EPIT1->CR = 0;
EPIT1->CR = (1 << 24 | frac << 4 | 1 << 3 | 1 << 2 | 1 << 1);
EPIT1->LR = value;
EPIT1->CMPR = 0;
GIC_EnableIRQ(EPIT1_IRQn);
EPIT1->CR |= 1 << 0;
}
void systick_handler(void *arg)
{
if (EPIT1->SR & (1 << 0)) {
tos_tick_handler();
}
EPIT1->SR |= 1 << 0;
}
void systick_init(k_tick_t tick_per_second)
{
epit1_init(0, 66000000 / tick_per_second);
tos_interrupt_handler_register(EPIT1_IRQn, (int_handler_t)systick_handler, NULL);
}

View File

@@ -0,0 +1,80 @@
/* Fuchsia's code is nice here, so I learn from it(fine, almost copy). thanks */
#include "exceptions.h"
.global arm_undefined
.global arm_syscall
.global arm_prefetch_abort
.global arm_data_abort
.global arm_reserved
.global arm_irq
.global arm_fiq
.extern tos_knl_irq_enter
.extern tos_knl_irq_leave
.extern interrupt_irq
.syntax unified
.text
.type arm_undefined, %function
arm_undefined:
save
/* r0 now holds pointer to iframe */
bl arm_undefined_handler
restore
.type arm_syscall, %function
arm_syscall:
b .
.type arm_prefetch_abort, %function
arm_prefetch_abort:
saveall_offset #4
/* r0 now holds pointer to iframe */
bl arm_prefetch_abort_handler
restoreall
.type arm_data_abort, %function
arm_data_abort:
saveall_offset #8
/* r0 now holds pointer to iframe */
bl arm_data_abort_handler
restoreall
.type arm_reserved, %function
arm_reserved:
b .
.type arm_irq, %function
arm_irq:
saveall_offset #4
/* r0 now holds pointer to iframe */
bl tos_knl_irq_enter
/* call into higher level code */
bl interrupt_irq
bl tos_knl_irq_leave
restoreall
.type arm_fiq, %function
arm_fiq:
b .
.end

View File

@@ -0,0 +1,133 @@
/* macros to align and unalign the stack on 8 byte boundary for ABI compliance */
.macro stack_align, tempreg
/* make sure the stack is aligned */
mov \tempreg, sp
tst sp, #4
subeq sp, #4
push { \tempreg }
/* tempreg holds the original stack */
.endm
.macro stack_restore, tempreg
/* restore the potentially unaligned stack */
pop { \tempreg }
mov sp, \tempreg
.endm
/* save and disable the vfp unit */
.macro vfp_save, temp1
/* save old fpexc */
vmrs \temp1, fpexc
push { \temp1 }
/* hard disable the vfp unit */
bic \temp1, #(1<<30)
vmsr fpexc, \temp1
.endm
/* restore the vfp enable/disable state */
.macro vfp_restore, temp1
/* restore fpexc */
pop { \temp1 }
vmsr fpexc, \temp1
.endm
/* Save callee trashed registers.
* At exit r0 contains a pointer to the register frame.
*/
.macro save
/* save spsr and r14 onto the svc stack */
srsdb #0x13!
/* switch to svc mode, interrupts disabled */
cpsid i, #0x13
/* save callee trashed regs and lr */
push { r0-r3, r12, lr }
#if 0
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
/* save and disable the vfp unit */
vfp_save r0
#endif
#endif
/* make sure the stack is 8 byte aligned */
stack_align r0
/* r0 now holds the pointer to the original iframe (before alignment) */
.endm
.macro save_offset, offset
sub lr, \offset
save
.endm
.macro restore
/* undo the stack alignment we did before */
stack_restore r0
#if 0
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
/* restore the old state of the vfp unit */
vfp_restore r0
#endif
#endif
pop { r0-r3, r12, lr }
/* return to whence we came from */
rfeia sp!
.endm
/* Save all registers.
* At exit r0 contains a pointer to the register frame.
*/
.macro saveall
/* save spsr and r14 onto the svc stack */
srsdb #0x13!
/* switch to svc mode, interrupts disabled */
cpsid i,#0x13
/* save all regs */
push { r0-r12, lr }
#if 0
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
/* save and disable the vfp unit */
vfp_save r0
#endif
#endif
/* make sure the stack is 8 byte aligned */
stack_align r0
/* r0 now holds the pointer to the original iframe (before alignment) */
.endm
.macro saveall_offset, offset
sub lr, \offset
saveall
.endm
.macro restoreall
/* undo the stack alignment we did before */
stack_restore r0
#if 0
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
/* restore the old state of the vfp unit */
vfp_restore r0
#endif
#endif
pop { r0-r12, r14 }
/* return to whence we came from */
rfeia sp!
.endm

View File

@@ -0,0 +1,73 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _PORT_H_
#define _PORT_H_
__PORT__ void port_int_disable(void);
__PORT__ void port_int_enable(void);
__PORT__ cpu_cpsr_t port_cpsr_save(void);
__PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr);
__PORT__ void port_cpu_reset(void);
__PORT__ void port_sched_start(void) __NO_RETURN__;
__PORT__ void port_context_switch(void);
__PORT__ void port_irq_context_switch(void);
__PORT__ void port_systick_config(uint32_t cycle_per_tick);
__PORT__ void port_systick_priority_set(uint32_t prio);
#if TOS_CFG_TICKLESS_EN > 0u
__PORT__ void port_systick_resume(void);
__PORT__ void port_systick_suspend(void);
__PORT__ void port_systick_reload(uint32_t cycle_per_tick);
__PORT__ void port_systick_pending_reset(void);
__PORT__ k_time_t port_systick_max_delay_millisecond(void);
#endif
#if TOS_CFG_PWR_MGR_EN > 0u
__PORT__ void port_sleep_mode_enter(void);
__PORT__ void port_stop_mode_enter(void);
__PORT__ void port_standby_mode_enter(void);
#endif
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
__PORT__ void HardFault_Handler(void);
__PORT__ void port_fault_diagnosis(void);
#endif
#endif /* _PORT_H_ */

View File

@@ -0,0 +1,134 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
__PORT__ void port_cpu_reset(void)
{
}
__PORT__ void port_systick_config(uint32_t cycle_per_tick)
{
}
__PORT__ void port_systick_priority_set(uint32_t prio)
{
}
#if TOS_CFG_TICKLESS_EN > 0u
__PORT__ k_time_t port_systick_max_delay_millisecond(void)
{
}
__PORT__ void port_systick_resume(void)
{
}
__PORT__ void port_systick_suspend(void)
{
}
__PORT__ void port_systick_reload(uint32_t cycle_per_tick)
{
}
__PORT__ void port_systick_pending_reset(void)
{
}
#endif
#if TOS_CFG_PWR_MGR_EN > 0u
__PORT__ void port_sleep_mode_enter(void)
{
#if 0
#if 1
HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
#else
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
#endif
#endif
}
__PORT__ void port_stop_mode_enter(void)
{
#if 0
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
#endif
}
__PORT__ void port_standby_mode_enter(void)
{
#if 0
HAL_PWR_EnterSTANDBYMode();
#endif
}
#endif
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
__PORT__ void port_fault_diagnosis(void)
{
// k_fault_log_writer("fault diagnosis does not supported in CORTEX M0\n");
}
#if 0
/*------------------ RealView Compiler -----------------*/
/* V5 */
#if defined(__CC_ARM)
__PORT__ __ASM__ void HardFault_Handler(void)
{
IMPORT fault_backtrace
MOV r0, lr
TST lr, #0x04
ITE EQ
MRSEQ r1, MSP
MRSNE r1, PSP
BL fault_backtrace
}
/*------------------ ARM Compiler V6 -------------------*/
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
__PORT__ void __NAKED__ HardFault_Handler(void)
{
__ASM__ __VOLATILE__ (
"MOV r0, lr\n\t"
"TST lr, #0x04\n\t"
"ITE EQ\n\t"
"MRSEQ r1, MSP\n\t"
"MRSNE r1, PSP\n\t"
"BL fault_backtrace\n\t"
);
}
#endif /* ARMCC VERSION */
#endif
#endif /* TOS_CFG_FAULT_BACKTRACE_EN */

View File

@@ -0,0 +1,35 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _PORT_CONFIG_H_
#define _PORT_CONFIG_H_
#define TOS_CFG_CPU_ADDR_SIZE CPU_WORD_SIZE_32
#define TOS_CFG_CPU_DATA_SIZE CPU_WORD_SIZE_32
#define TOS_CFG_CPU_STK_GROWTH CPU_STK_GROWTH_DESCENDING
// #define TOS_CFG_CPU_HRTIMER_SIZE CPU_WORD_SIZE_32
#define TOS_CFG_CPU_HRTIMER_EN 0u
#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 0u
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
#define TOS_CFG_CPU_ARM_FPU_EN 1u
#else
#define TOS_CFG_CPU_ARM_FPU_EN 0u
#endif
#endif /* _PORT_CONFIG_H_ */

View File

@@ -0,0 +1,82 @@
.global port_int_disable
.global port_int_enable
.global port_cpsr_save
.global port_cpsr_restore
.global port_sched_start
.global port_context_switch
.global port_irq_context_switch
.extern k_curr_task
.extern k_next_task
.syntax unified
.align 2
.text
.type port_int_disable, %function
port_int_disable:
CPSID I
.type port_int_enable, %function
port_int_enable:
CPSIE I
.type port_cpsr_save, %function
port_cpsr_save:
MRS R0, CPSR
CPSID I
BX LR
.type port_cpsr_restore, %function
port_cpsr_restore:
MSR CPSR, R0
BX LR
.type port_sched_start, %function
port_sched_start:
B .L__context_restore
.type port_context_switch, %function
port_context_switch:
.L__context_save:
STR R0, [SP, #-0xC] /* backup R0 */
MRS R0, CPSR
TST LR, #0x01
ORRNE R0, R0, 0x20 /* set thumb bit*/
STMFD SP!, { R0 } /* save CPSR */
STMFD SP!, { LR } /* save PC */
LDR R0, [SP, #-0x4] /* restore R0 */
STMFD SP!, { R0 - R12, LR }
/* k_curr_task->sp = SP */
LDR R0, =k_curr_task
LDR R0, [R0]
STR SP, [R0]
.L__context_restore:
/* k_curr_task = k_next_task */
LDR R0, =k_next_task
LDR R0, [R0]
LDR R1, =k_curr_task
STR R0, [R1]
/* SP = k_next_task->sp */
LDR SP, [R0]
LDMFD SP!, { R0 - R12, LR }
RFEIA SP!
.type port_irq_context_switch, %function
port_irq_context_switch:
/* we already store the k_curr_task's context onto its stack by arm_irq(see saveall_offset) */
/* ATTENTION:
our kernel always runs in SVC mode even in user task,
if one day we make the user task run in USR mode(although I cannot see any meaning to do this in RTOS),
we must deal with more logic
*/
B .L__context_restore /* magnificent */

View File

@@ -0,0 +1,150 @@
.equ MODE_USR, 0x10
.equ MODE_FIQ, 0x11
.equ MODE_IRQ, 0x12
.equ MODE_SVC, 0x13
.equ MODE_ABT, 0x17
.equ MODE_UND, 0x1B
.equ MODE_SYS, 0x1F
.equ BIT_I, 0x80 @ when I bit is set, IRQ is disabled
.equ BIT_F, 0x40 @ when F bit is set, FIQ is disabled
.equ STACK_SIZE_USR, 0x00000100
.equ STACK_SIZE_FIQ, 0x00000100
.equ STACK_SIZE_IRQ, 0x00001000
.equ STACK_SIZE_ABT, 0x00000100
.equ STACK_SIZE_UND, 0x00000100
.equ STACK_SIZE_SYS, 0x00000800
.equ STACK_SIZE_SVC, 0x00001000
.syntax unified
.section ".text.vector", "ax"
.code 32
.align 0
.global _start
_start:
_vector:
ldr pc, vector_reset
ldr pc, vector_undefined
ldr pc, vector_swi
ldr pc, vector_prefetch_abort
ldr pc, vector_data_abort
ldr pc, vector_reserved
ldr pc, vector_irq
ldr pc, vector_fiq
.align 3
vector_reset:
.word arm_reset
vector_undefined:
.word arm_undefined
vector_swi:
.word arm_syscall
vector_prefetch_abort:
.word arm_prefetch_abort
vector_data_abort:
.word arm_data_abort
vector_reserved:
.word arm_reserved
vector_irq:
.word arm_irq
vector_fiq:
.word arm_fiq
.section ".text", "ax"
.global arm_reset
arm_reset:
.L__cache_disable:
mrc p15, 0, r12, c1, c0, 0 /* read SCTLR */
bic r12, #(1 << 12) /* i-cache disable */
bic r12, #(1 << 2 | 1 << 0) /* d-cache, mmu disable */
mcr p15, 0, r12, c1, c0, 0 /* write SCTLR */
/* set up the stack */
.L__stack_setup:
cpsid i, #MODE_IRQ /* irq */
ldr sp, =__irq_stack_limit
cpsid i, #MODE_FIQ /* fiq */
ldr sp, =__fiq_stack_limit
cpsid i, #MODE_ABT /* abort */
ldr sp, =__abt_stack_limit
cpsid i, #MODE_UND /* undefined */
ldr sp, =__und_stack_limit
cpsid i, #MODE_SYS /* system */
ldr sp, =__sys_stack_limit
cpsid i, #MODE_SVC /* supervisor */
ldr sp, =__svc_stack_limit
/* init vector table */
.L__vector_setup:
dsb
isb
ldr r0, =_vector
mcr p15, 0, r0, c12, c0, #0 /* write VBAR */
dsb
isb
/* clear bss */
.L__bss_clear:
ldr r0, =__bss_start__
ldr r1, =__bss_end__
mov r2, #0
.L__bss_loop:
cmp r0, r1
strlt r2, [r0], #4
blt .L__bss_loop
bl main
b .
.section ".bss.prebss.exc_stk", "wa"
.bss
.align 2
__usr_stack_base:
.space STACK_SIZE_USR
__usr_stack_limit:
__fiq_stack_base:
.space STACK_SIZE_FIQ
__fiq_stack_limit:
__irq_stack_base:
.space STACK_SIZE_IRQ
__irq_stack_limit:
__abt_stack_base:
.space STACK_SIZE_ABT
__abt_stack_limit:
__und_stack_base:
.space STACK_SIZE_UND
__und_stack_limit:
__sys_stack_base:
.space STACK_SIZE_SYS
__sys_stack_limit:
__svc_stack_base:
.space STACK_SIZE_SVC
__svc_stack_limit:
.size __usr_stack_base, . - __usr_stack_base
.end

View File

@@ -0,0 +1,90 @@
#include "chip/chip.h"
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = KERNEL_BASE;
_start = .;
.text : AT(KERNEL_BASE) {
__text_start = .;
KEEP(*(.text.vector))
*(.text)
*(.text.*)
KEEP(*(.init))
KEEP(*(.fini))
}
.ARM.extab : ALIGN(4) {
*(.ARM.extab* .gnu.linkonce.armextab.*)
}
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
.ARM.exidx : ALIGN(4) {
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
}
__exidx_end = .;
.dummy_post_text : {
__text_end = .;
}
.rodata : ALIGN(4) {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
}
.dummy_post_rodata : {
__rodata_end = .;
}
.data : ALIGN(4) {
__data_start = .;
*(.data)
*(.data.*)
}
.ctors : ALIGN(4) {
__ctor_list = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.ctors .init_array*))
__ctor_end = .;
}
.dtors : ALIGN(4) {
__dtor_list = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.dtors .fini_array*))
__dtor_end = .;
}
.dummy_post_rodata : {
__data_end = .;
}
.bss : ALIGN(4) {
KEEP(*(.bss.prebss.*))
. = ALIGN(4);
__bss_start__ = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
}
_end = .;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note) }
}

View File

@@ -15,7 +15,7 @@
* within TencentOS. * within TencentOS.
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#include <tos_k.h> #include "tos_k.h"
__API__ uint32_t tos_cpu_clz(uint32_t val) __API__ uint32_t tos_cpu_clz(uint32_t val)
{ {

View File

@@ -15,7 +15,7 @@
* within TencentOS. * within TencentOS.
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#include <tos_k.h> #include "tos_k.h"
__API__ uint32_t tos_cpu_clz(uint32_t val) __API__ uint32_t tos_cpu_clz(uint32_t val)
{ {

View File

@@ -15,7 +15,7 @@
* within TencentOS. * within TencentOS.
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#include <tos_k.h> #include "tos_k.h"
__API__ uint32_t tos_cpu_clz(uint32_t val) __API__ uint32_t tos_cpu_clz(uint32_t val)
{ {

View File

@@ -361,3 +361,4 @@ irq_task_switch:
sw s11, __reg_s11__OFFSET(sp) sw s11, __reg_s11__OFFSET(sp)
j switch_task j switch_task

View File

@@ -0,0 +1,126 @@
TOP_DIR := ../..
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET ?= TencentOS_tiny
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
GCC_VERSION := 6.5.0 # 4.9.4
LD_SCRIPT_S := link.ld.S
LD_SCRIPT_DIR := $(TOP_DIR)/arch/arm/arm-v7a/lds
LD_SCRIPT := link.ld
GCC_DIR := D:\Green\gcc-arm-linux-gnueabihf
OUT_ROOT := out
OBJ_DIR := obj
LIB_DIR := lib
TARGET_DIR := target
OUT_DIR := $(OUT_ROOT)/$(OBJ_DIR) $(OUT_ROOT)/$(LIB_DIR) $(OUT_ROOT)/$(TARGET_DIR)
NOECHO := @
LIBPATH := -lgcc -L$(GCC_DIR)/lib/gcc/arm-linux-gnueabihf/$(GCC_VERSION)
INCDIRS := \
$(TOP_DIR)/kernel/core/include \
$(TOP_DIR)/kernel/pm/include \
$(TOP_DIR)/arch/arm/arm-v7a/common/include \
$(TOP_DIR)/arch/arm/arm-v7a/cortex-a7/gcc \
$(TOP_DIR)/arch/arm/arm-v7a/cortex-a7/chip/imx6ul/include \
imx6ul \
TOS_CONFIG \
stdio/include \
bsp/clk \
bsp/led \
bsp/delay \
bsp/beep \
bsp/gpio \
bsp/key \
bsp/exit \
bsp/int \
bsp/epittimer \
bsp/keyfilter \
bsp/uart \
bsp/lcd \
bsp/rtc \
bsp/i2c \
bsp/ap3216c \
bsp/spi \
bsp/icm20608 \
bsp/touchscreen \
bsp/backlight
SRCDIRS := \
src \
$(TOP_DIR)/kernel/core \
$(TOP_DIR)/arch/arm/arm-v7a/cortex-a7/gcc \
$(TOP_DIR)/arch/arm/arm-v7a/common \
$(TOP_DIR)/arch/arm/arm-v7a/cortex-a7/chip/imx6ul \
stdio/lib \
bsp/clk \
bsp/led \
bsp/delay \
bsp/beep \
bsp/gpio \
bsp/key \
bsp/exit \
bsp/int \
bsp/epittimer \
bsp/keyfilter \
bsp/uart \
bsp/lcd \
bsp/rtc \
bsp/i2c \
bsp/ap3216c \
bsp/spi \
bsp/icm20608 \
bsp/touchscreen \
bsp/backlight
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
SOBJS := $(patsubst %, $(OUT_ROOT)/$(OBJ_DIR)/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, $(OUT_ROOT)/$(OBJ_DIR)/%, $(CFILENDIR:.c=.o))
OBJS := $(SOBJS) $(COBJS)
VPATH := $(SRCDIRS)
.PHONY: clean $(OUT_DIR)
$(TARGET).bin : $(OUT_DIR) $(OBJS) $(LD_SCRIPT)
@echo "LD $(TARGET).elf"
$(NOECHO)$(LD) -T$(LD_SCRIPT) -o $(OUT_ROOT)/$(TARGET_DIR)/$(TARGET).elf $(OBJS) $(LIBPATH)
@echo "OBJCOPY $(TARGET).bin"
$(NOECHO)$(OBJCOPY) -O binary -S $(OUT_ROOT)/$(TARGET_DIR)/$(TARGET).elf $(OUT_ROOT)/$(TARGET_DIR)/$@
@echo "OBJDUMP $(TARGET).asm"
$(NOECHO)$(OBJDUMP) -D -m arm $(OUT_ROOT)/$(TARGET_DIR)/$(TARGET).elf > $(OUT_ROOT)/$(TARGET_DIR)/$(TARGET).asm
$(LD_SCRIPT): $(LD_SCRIPT_DIR)/$(LD_SCRIPT_S)
@echo "generate link script"
$(NOECHO)$(CC) $(INCLUDE) -E -P -o $@ $<
$(OUT_DIR) :
@mkdir -p $@
# $(NOECHO)$(CC) -march=armv7-a -nostdlib -fno-builtin -Wall -c -O2 $(INCLUDE) -o $@ $<
$(SOBJS) : $(OUT_ROOT)/$(OBJ_DIR)/%.o : %.S
@echo "CC $(notdir $<)"
$(NOECHO)$(CC) -Wall -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
# $(NOECHO)$(CC) -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -Wall -c -O2 $(INCLUDE) -o $@ $<
$(COBJS) : $(OUT_ROOT)/$(OBJ_DIR)/%.o : %.c
@echo "CC $(notdir $<)"
$(NOECHO)$(CC) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
clean:
@rm -rf $(OUT_ROOT) $(LD_SCRIPT)

View File

@@ -0,0 +1,18 @@
# TencentOS tiny Cortex V7-A支持(基于正点原子阿尔法alpha开发板)
## 如何运行
1. 安装arm交叉编译器本构建采用6.5.0版本)
2. 在TencentOS-tiny\board\ALPHA_I.MX_emmc_256ddr目录下根据自己的arm交叉编译器版本及安装目录对应修改Makefile中的如下变量
- GCC_VERSION
- GCC_DIR
3. 在TencentOS-tiny\board\ALPHA_I.MX_emmc_256ddr目录下执行make命令
4. 利用正点原子官方的imxdownload工具将out/target/TencenOS_tiny.bin烧写到SD卡中
5. 将SD卡插入阿尔法开发板接上串口开发板复位上电可从串口中看到两个任务以一定的时序交叉运行业务入口文件为TencentOS-tiny\board\ALPHA_I.MX_emmc_256ddr\src\main.c
## 注意
1. 正点原子阿尔法开发板的相关板级驱动,由正点原子官方示例提供,并已提前征得正点原子官方同意将相关源码作为示例代码集成。
2. 正点原子官方烧写工具目前只支持linux平台。
3. 后续TencentOS tiny会集成自己的镜像烧写工具原子官方的烧写工具可定制性稍有欠缺

View File

@@ -0,0 +1,53 @@
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#define TOS_CFG_TASK_PRIO_MAX 10u
#define TOS_CFG_ROUND_ROBIN_EN 0u
#define TOS_CFG_OBJECT_VERIFY_EN 1u
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 0u
#define TOS_CFG_EVENT_EN 1u
#define TOS_CFG_MMBLK_EN 1u
#define TOS_CFG_MMHEAP_EN 1u
#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x8000
#define TOS_CFG_MUTEX_EN 1u
#define TOS_CFG_MESSAGE_QUEUE_EN 1u
#define TOS_CFG_MAIL_QUEUE_EN 1u
#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u
#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u
#define TOS_CFG_TIMER_EN 0u
#define TOS_CFG_PWR_MGR_EN 0u
#define TOS_CFG_TICKLESS_EN 0u
#define TOS_CFG_SEM_EN 1u
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u
#define TOS_CFG_FAULT_BACKTRACE_EN 0u
#define TOS_CFG_IDLE_TASK_STK_SIZE 512u
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
#define TOS_CFG_CPU_CLOCK 528000000
#define TOS_CFG_TIMER_AS_PROC 1u
#endif

View File

@@ -0,0 +1,139 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_ap3216c.c
作者 : 左忠凯
版本 : V1.0
描述 : AP3216C驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/3/26 左忠凯创建
***************************************************************/
#include "bsp_ap3216c.h"
#include "bsp_i2c.h"
#include "bsp_delay.h"
#include "cc.h"
#include "printf.h"
/*
* @description : 初始化AP3216C
* @param : 无
* @return : 0 成功,其他值 错误代码
*/
unsigned char ap3216c_init(void)
{
unsigned char data = 0;
/* 1、IO初始化配置I2C IO属性
* I2C1_SCL -> UART4_TXD
* I2C1_SDA -> UART4_RXD
*/
IOMUXC_SetPinMux(IOMUXC_UART4_TX_DATA_I2C1_SCL, 1);
IOMUXC_SetPinMux(IOMUXC_UART4_RX_DATA_I2C1_SDA, 1);
/*
*bit 16:0 HYS关闭
*bit [15:14]: 1 默认47K上拉
*bit [13]: 1 pull功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 驱动能力为R0/6
*bit [0]: 1 高转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART4_TX_DATA_I2C1_SCL, 0x70B0);
IOMUXC_SetPinConfig(IOMUXC_UART4_RX_DATA_I2C1_SDA, 0X70B0);
i2c_init(I2C1); /* 初始化I2C1 */
/* 2、初始化AP3216C */
ap3216c_writeonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG, 0X04); /* 复位AP3216C */
delayms(50); /* AP33216C复位至少10ms */
ap3216c_writeonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG, 0X03); /* 开启ALS、PS+IR */
data = ap3216c_readonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG); /* 读取刚刚写进去的0X03 */
if(data == 0X03)
return 0; /* AP3216C正常 */
else
return 1; /* AP3216C失败 */
}
/*
* @description : 向AP3216C写入数据
* @param - addr: 设备地址
* @param - reg : 要写入的寄存器
* @param - data: 要写入的数据
* @return : 操作结果
*/
unsigned char ap3216c_writeonebyte(unsigned char addr,unsigned char reg, unsigned char data)
{
unsigned char status=0;
unsigned char writedata=data;
struct i2c_transfer masterXfer;
/* 配置I2C xfer结构体 */
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Write; /* 写入数据 */
masterXfer.subaddress = reg; /* 要写入的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = &writedata; /* 要写入的数据 */
masterXfer.dataSize = 1; /* 写入数据长度1个字节 */
if(i2c_master_transfer(I2C1, &masterXfer))
status=1;
return status;
}
/*
* @description : 从AP3216C读取一个字节的数据
* @param - addr: 设备地址
* @param - reg : 要读取的寄存器
* @return : 读取到的数据。
*/
unsigned char ap3216c_readonebyte(unsigned char addr,unsigned char reg)
{
unsigned char val=0;
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Read; /* 读取数据 */
masterXfer.subaddress = reg; /* 要读取的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = &val; /* 接收数据缓冲区 */
masterXfer.dataSize = 1; /* 读取数据长度1个字节 */
i2c_master_transfer(I2C1, &masterXfer);
return val;
}
/*
* @description : 读取AP3216C的数据读取原始数据包括ALS,PS和IR, 注意!
* : 如果同时打开ALS,IR+PS的话两次数据读取的时间间隔要大于112.5ms
* @param - ir : ir数据
* @param - ps : ps数据
* @param - ps : als数据
* @return : 无。
*/
void ap3216c_readdata(unsigned short *ir, unsigned short *ps, unsigned short *als)
{
unsigned char buf[6];
unsigned char i;
/* 循环读取所有传感器数据 */
for(i = 0; i < 6; i++)
{
buf[i] = ap3216c_readonebyte(AP3216C_ADDR, AP3216C_IRDATALOW + i);
}
if(buf[0] & 0X80) /* IR_OF位为1,则数据无效 */
*ir = 0;
else /* 读取IR传感器的数据 */
*ir = ((unsigned short)buf[1] << 2) | (buf[0] & 0X03);
*als = ((unsigned short)buf[3] << 8) | buf[2]; /* 读取ALS传感器的数据 */
if(buf[4] & 0x40) /* IR_OF位为1,则数据无效 */
*ps = 0;
else /* 读取PS传感器的数据 */
*ps = ((unsigned short)(buf[5] & 0X3F) << 4) | (buf[4] & 0X0F);
}

View File

@@ -0,0 +1,36 @@
#ifndef _BSP_AP3216C_H
#define _BSP_AP3216C_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_ap3216c.h
作者 : 左忠凯
版本 : V1.0
描述 : AP3216C驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/3/26 左忠凯创建
***************************************************************/
#include "bsp.h"
#define AP3216C_ADDR 0X1E /* AP3216C器件地址 */
/* AP3316C寄存器 */
#define AP3216C_SYSTEMCONG 0x00 /* 配置寄存器 */
#define AP3216C_INTSTATUS 0X01 /* 中断状态寄存器 */
#define AP3216C_INTCLEAR 0X02 /* 中断清除寄存器 */
#define AP3216C_IRDATALOW 0x0A /* IR数据低字节 */
#define AP3216C_IRDATAHIGH 0x0B /* IR数据高字节 */
#define AP3216C_ALSDATALOW 0x0C /* ALS数据低字节 */
#define AP3216C_ALSDATAHIGH 0X0D /* ALS数据高字节 */
#define AP3216C_PSDATALOW 0X0E /* PS数据低字节 */
#define AP3216C_PSDATAHIGH 0X0F /* PS数据高字节 */
/* 函数声明 */
unsigned char ap3216c_init(void);
unsigned char ap3216c_readonebyte(unsigned char addr,unsigned char reg);
unsigned char ap3216c_writeonebyte(unsigned char addr,unsigned char reg, unsigned char data);
void ap3216c_readdata(unsigned short *ir, unsigned short *ps, unsigned short *als);
#endif

View File

@@ -0,0 +1,160 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_backlight.c
作者 : 左忠凯
版本 : V1.0
描述 : LCD背光PWM驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/22 左忠凯创建
***************************************************************/
#include "bsp_backlight.h"
#include "bsp_int.h"
#include "printf.h"
/* 背光设备 */
struct backlight_dev_struc backlight_dev;
/*
* @description : pwm1中断处理函数
* @param : 无
* @return : 无
*/
void pwm1_irqhandler(void)
{
if(PWM1->PWMSR & (1 << 3)) /* FIFO为空中断 */
{
/* 将占空比信息写入到FIFO中,其实就是设置占空比 */
pwm1_setduty(backlight_dev.pwm_duty);
PWM1->PWMSR |= (1 << 3); /* 写1清除中断标志位 */
}
}
/*
* @description : 初始化背光PWM
* @param : 无
* @return : 无
*/
void backlight_init(void)
{
unsigned char i = 0;
/* 1、背光PWM IO初始化 */
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_PWM1_OUT, 0); /* 复用为PWM1_OUT */
/* 配置PWM IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 10 100K上拉
*bit [13]: 1 pull功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 010 驱动能力为R0/2
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_PWM1_OUT, 0XB090);
/* 2、初始化PWM1 */
/*
* 初始化寄存器PWMCR
* bit[27:26] : 01 当FIFO中空余位置大于等于2的时候FIFO空标志值位
* bit[25] :
0 停止模式下PWM不工作
* bit[24] : 0 休眠模式下PWM不工作
* bit[23] : 0 等待模式下PWM不工作
* bit[22] : 0 调试模式下PWM不工作
* bit[21] : 0 关闭字节交换
* bit[20] : 0 关闭半字数据交换
* bit[19:18] : 00 PWM输出引脚在计数器重新计数的时候输出高电平
* 在计数器计数值达到比较值以后输出低电平
* bit[17:16] : 01 PWM时钟源选择IPG CLK = 66MHz
* bit[15:4] : 65 分频系数为65+1=66PWM时钟源 = 66MHZ/66=1MHz
* bit[3] : 0 PWM不复位
* bit[2:1] : 00 FIFO中的sample数据每个只能使用一次。
* bit[0] : 0 先关闭PWM后面再使能
*/
PWM1->PWMCR = 0; /* 寄存器先清零 */
PWM1->PWMCR |= (1 << 26) | (1 << 16) | (65 << 4);
/* 设置PWM周期为1000,那么PWM频率就是1M/1000 = 1KHz。 */
pwm1_setperiod_value(1000);
/* 设置占空比默认50%占空比 ,写四次是因为有4个FIFO */
backlight_dev.pwm_duty = 50;
for(i = 0; i < 4; i++)
{
pwm1_setduty(backlight_dev.pwm_duty);
}
/* 使能FIFO空中断设置寄存器PWMIR寄存器的bit0为1 */
PWM1->PWMIR |= 1 << 0;
system_register_irqhandler(PWM1_IRQn, (system_irq_handler_t)pwm1_irqhandler, NULL); /* 注册中断服务函数 */
GIC_EnableIRQ(PWM1_IRQn); /* 使能GIC中对应的中断 */
PWM1->PWMSR = 0; /* PWM中断状态寄存器清零 */
pwm1_enable(); /* 使能PWM1 */
}
/*
* @description : 使能PWM
* @param : 无
* @return : 无
*/
void pwm1_enable(void)
{
PWM1->PWMCR |= 1 << 0;
}
/*
* @description : 设置Sample寄存器Sample数据会写入到FIFO中
* 所谓的Sample寄存器就相当于比较寄存器假如PWMCR中的POUTC
* 设置为00的时候。当PWM计数器中的计数值小于Sample的时候
* 就会输出高电平当PWM计数器值大于Sample的时候输出底电平,
* 因此可以通过设置Sample寄存器来设置占空比
* @param - value : 寄存器值范围0~0XFFFF
* @return : 无
*/
void pwm1_setsample_value(unsigned int value)
{
PWM1->PWMSAR = (value & 0XFFFF);
}
/*
* @description : 设置PWM周期就是设置寄存器PWMPRPWM周期公式如下
* PWM_FRE = PWM_CLK / (PERIOD + 2) 比如当前PWM_CLK=1MHz
* 要产生1KHz的PWM那么PERIOD = 1000000/1K - 2 = 998
* @param - value : 周期值范围0~0XFFFF
* @return : 无
*/
void pwm1_setperiod_value(unsigned int value)
{
unsigned int regvalue = 0;
if(value < 2)
regvalue = 2;
else
regvalue = value - 2;
PWM1->PWMPR = (regvalue & 0XFFFF);
}
/*
* @description : 设置PWM占空比
* @param - value : 占空比0~100对应0%~100%
* @return : 无
*/
void pwm1_setduty(unsigned char duty)
{
unsigned short preiod;
unsigned short sample;
backlight_dev.pwm_duty = duty;
preiod = PWM1->PWMPR + 2;
sample = preiod * backlight_dev.pwm_duty / 100;
pwm1_setsample_value(sample);
}

View File

@@ -0,0 +1,30 @@
#ifndef _BACKLIGHT_H
#define _BACKLIGHT_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_backlight.c
作者 : 左忠凯
版本 : V1.0
描述 : LCD背光PWM驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/22 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 背光PWM结构体 */
struct backlight_dev_struc
{
unsigned char pwm_duty; /* 占空比 */
};
/* 函数声明 */
void backlight_init(void);
void pwm1_enable(void);
void pwm1_setsample_value(unsigned int value);
void pwm1_setperiod_value(unsigned int value);
void pwm1_setduty(unsigned char duty);
void pwm1_irqhandler(void);
#endif

View File

@@ -0,0 +1,54 @@
#include "bsp_beep.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_beep.c
作者 : 左忠凯
版本 : V1.0
描述 : 蜂鸣器驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
/*
* @description : 初始化蜂鸣器对应的IO
* @param : 无
* @return : 无
*/
void beep_init(void)
{
/* 1、初始化IO复用复用为GPIO5_IO01 */
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0);
/* 2、、配置GPIO1_IO03的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 R0/6驱动能力
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0X10B0);
/* 3、初始化GPIO,GPIO5_IO01设置为输出 */
GPIO5->GDIR |= (1 << 1);
/* 4、设置GPIO5_IO01输出高电平关闭蜂鸣器 */
GPIO5->DR |= (1 << 1);
}
/*
* @description : 蜂鸣器控制函数,控制蜂鸣器打开还是关闭
* @param - status : 0关闭蜂鸣器1 打开蜂鸣器
* @return : 无
*/
void beep_switch(int status)
{
if(status == ON)
GPIO5->DR &= ~(1 << 1); /* 打开蜂鸣器 */
else if(status == OFF)
GPIO5->DR |= (1 << 1); /* 关闭蜂鸣器 */
}

View File

@@ -0,0 +1,20 @@
#ifndef __BSP_BEEP_H
#define __BSP_BEEP_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_beep.h
作者 : 左忠凯
版本 : V1.0
描述 : 蜂鸣器驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 函数声明 */
void beep_init(void);
void beep_switch(int status);
#endif

View File

@@ -0,0 +1,291 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_bmp280.
作者 : 左忠凯
版本 : V1.0
描述 : BMP280驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/17 左忠凯创建
***************************************************************/
#include "bsp_bmp280.h"
#include "bsp_delay.h"
#include "bsp_spi.h"
#include "printf.h"
/* BMP280属性结构体 */
struct bmp280_dev_struc bmp280_dev;
/*
* @description : 初始化BMP280
* @param : 无
* @return : 0 初始化成功,其他值 初始化失败
*/
unsigned char bmp280_init(void)
{
unsigned char regvalue;
gpio_pin_config_t cs_config;
/* 1、初始化SPI */
spi3_init();
/* 2、初始化片选引脚 */
IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0);
IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0X10B0);
cs_config.direction = kGPIO_DigitalOutput;
cs_config.outputLogic = 1;
gpio_init(GPIO1, 20, &cs_config);
/* 4、配置BMP280 */
regvalue = bmp280_read_reg(BMP280_ID_REG);/* 读取ID */
if(regvalue == BMP280_ID_VALUE)
{
printf("bmp280 id = %#X\r\n", regvalue);
} else {
return 1;
}
bmp280_write_reg(BMP280_RESET_REG, BMP280_RESET_VALUE); /* 复位BMP280 */
bmp280_write_reg(BMP280_CTRLMEAS_REG, 0); /* 进入睡眠模式才可以写控制寄存器 */
/* 设置BMP280使用Ultra high resolution模式
* osrs_p为X16osrs_t为X2IIR Filter为16
*/
/*
*配置BMP280控制寄存器CONFIG_REG
*bit[7:5] : 000 normal模式下的T_standby0.5ms
*bit[4:2] : 111 IIR滤波器的时间常量 X16
*bit[0] : 0 禁止3线SPI模式
*/
bmp280_write_reg(BMP280_CONFIG_REG, 0x1C);
/*
*配置BMP280测量寄存器CTRLMEAS_REG
*bit[7:5] : 010 温度采样率x2 17bit/0.0025°C
*bit[4:2] : 111 压力采样率x16 20bit/0.16Pa
*bit[1:0] : 11 normal模式
*/
bmp280_write_reg(BMP280_CTRLMEAS_REG, 0x5F);
bmp280_get_calibparam(); /* 计算参数 */
return 0;
}
/*
* @description : 计算BMP280的计算参数
* @param : 无
* @return : 无
*/
void bmp280_get_calibparam(void)
{
unsigned char param_buf[BMP280_TRIMPARAM_LEN];
/* 读取BMP280的参数 */
bmp280_read_len(BMP280_TRIMPARAM_FRG, param_buf, BMP280_TRIMPARAM_LEN);
/* 计算参数 */
bmp280_dev.calib_param.dig_T1 = (u16)((((u16)((u8)param_buf[1])) << 8) | param_buf[0]);
bmp280_dev.calib_param.dig_T2 = (s16)((((s16)((s8)param_buf[3])) << 8) | param_buf[2]);
bmp280_dev.calib_param.dig_T3 = (s16)((((s16)((s8)param_buf[5])) << 8) | param_buf[4]);
bmp280_dev.calib_param.dig_P1 = (u16)((((u16)((u8)param_buf[7])) << 8) | param_buf[6]);
bmp280_dev.calib_param.dig_P2 = (s16)((((s16)((s8)param_buf[9])) << 8) | param_buf[8]);
bmp280_dev.calib_param.dig_P3 = (s16)((((s16)((s8)param_buf[11])) << 8) | param_buf[10]);
bmp280_dev.calib_param.dig_P4 = (s16)((((s16)((s8)param_buf[13])) << 8) | param_buf[12]);
bmp280_dev.calib_param.dig_P5 = (s16)((((s16)((s8)param_buf[15])) << 8) | param_buf[14]);
bmp280_dev.calib_param.dig_P6 = (s16)((((s16)((s8)param_buf[17])) << 8) | param_buf[16]);
bmp280_dev.calib_param.dig_P7 = (s16)((((s16)((s8)param_buf[19])) << 8) | param_buf[18]);
bmp280_dev.calib_param.dig_P8 = (s16)((((s16)((s8)param_buf[21])) << 8) | param_buf[20]);
bmp280_dev.calib_param.dig_P9 = (s16)((((s16)((s8)param_buf[23])) << 8) | param_buf[22]);
}
/*
* @description : 读取BMP280寄存器值
* @param - reg : 要读取的寄存器地址
* @return : 读取到的寄存器值
*/
unsigned char bmp280_read_reg(unsigned char reg)
{
unsigned char reg_val;
/* BMP280在使用SPI接口的时候寄存器地址
* 只有低7位有效,寄存器地址最高位是读/写标志位
* 读的时候要为1写的时候要为0。
*/
reg |= 0x80;
BMP280_CSN(0); /* 使能SPI传输 */
spi3ch0_readwrite_byte(reg); /* 发送寄存器地址 */
reg_val = spi3ch0_readwrite_byte(0XFF); /* 读取寄存器的值 */
BMP280_CSN(1); /* 禁止SPI传输 */
return(reg_val); /* 返回读取到的寄存器值 */
}
/*
* @description : 读取BMP280连续多个寄存器
* @param - reg : 要读取的寄存器地址
* @return : 读取到的寄存器值
*/
void bmp280_read_len(unsigned char reg, unsigned char *buf, unsigned char len)
{
unsigned char i;
/* BMP280在使用SPI接口的时候寄存器地址
* 只有低7位有效,寄存器地址最高位是读/写标志位
* 读的时候要为1写的时候要为0。
*/
reg |= 0x80;
BMP280_CSN(0); /* 使能SPI传输 */
spi3ch0_readwrite_byte(reg); /* 发送寄存器地址 */
for(i = 0; i < len; i++) /* 顺序读取寄存器的值 */
{
buf[i]=spi3ch0_readwrite_byte(0XFF);
}
BMP280_CSN(1); /* 禁止SPI传输 */
}
/*
* @description : 写BMP280指定寄存器
* @param - reg : 要读取的寄存器地址
* @param - value: 要写入的值
* @return : 无
*/
void bmp280_write_reg(unsigned char reg, unsigned char value)
{
/* BMP280在使用SPI接口的时候寄存器地址
* 只有低7位有效,寄存器地址最高位是读/写标志位
* 读的时候要为1写的时候要为0。
*/
reg &= ~0x80;
BMP280_CSN(0); /* 使能SPI传输 */
spi3ch0_readwrite_byte(reg); /* 发送寄存器地址 */
spi3ch0_readwrite_byte(value); /* 发送要写入的值 */
BMP280_CSN(1); /* 禁止SPI传输 */
}
/*
* @description : 获取BMP280原始的温度数据值
* @param : 无
* @return : 原始的温度数据值
*/
signed int bmp280_get_uncomptemp(void)
{
unsigned char temp_value[3];
signed int uncomp_temp = 0;
bmp280_read_len(BMP280_TEMPMSB_REG, temp_value, 3);
uncomp_temp = (s32)((((u32)(temp_value[0])) << 12)
| (((u32)(temp_value[1])) << 4)
| ((u32)temp_value[2] >> 4));
return uncomp_temp;
}
/*
* @description : 获取BMP280原始的压力数据值
* @param : 无
* @return : 原始的温度数据值
*/
signed int bmp280_get_uncomppres(void)
{
unsigned char pres_value[3];
signed int uncomp_pres = 0;
bmp280_read_len(BMP280_PRESMSB_REG, pres_value, 3);
uncomp_pres = (s32)((((u32)(pres_value[0])) << 12)
| (((u32)(pres_value[1])) << 4)
| ((u32)pres_value[2] >> 4));
return uncomp_pres;
}
/*
* @description : 从BMP280的原始温度数据值计算出真实的温度数据值
* @param - uncomptemp : 原始的温度数据值
* @return : 得到的真实的数据值这里将温度值扩大了100倍
* 比如5123 = 51.23°C。
*/
signed int bmp280_get_actualtemp(signed int uncomptemp)
{
s32 v_x1_u32r = 0, v_x2_u32r = 0;
s32 temperature = 0;
/* 计算温度值X1 */
v_x1_u32r = ((((uncomptemp >> 3) - ((s32)bmp280_dev.calib_param.dig_T1 << 1)))
* ((s32)bmp280_dev.calib_param.dig_T2)) >> 11;
/* 计算温度值X2 */
v_x2_u32r = (((((uncomptemp >> 4)- ((s32)bmp280_dev.calib_param.dig_T1))
* ((uncomptemp >> 4) - ((s32)bmp280_dev.calib_param.dig_T1))) >> 12)
* ((s32)bmp280_dev.calib_param.dig_T3)) >> 14;
/* 计算t_fine */
bmp280_dev.calib_param.t_fine = v_x1_u32r + v_x2_u32r;
/* 计算真实的温度值 */
temperature = (bmp280_dev.calib_param.t_fine * 5 + 128) >> 8;
return temperature;
}
/*
* @description : 从BMP280的原始气压数据值计算出真实的气压数据值
* @param - uncomppres : 原始的气压数据值
* @return : 得到的真实的气压数据值比如23658就是:
* 23658Pa = 236.58hPa = 236.58 milllibar。
*/
unsigned int bmp280_get_actualpres(s32 uncomppres)
{
s32 v_x1_u32r = 0;
s32 v_x2_u32r = 0;
u32 v_pressure_u32 = 0;
/* 计算X1 */
v_x1_u32r = (((s32)bmp280_dev.calib_param.t_fine) >> 1) - (s32)64000;
/* 计算X2*/
v_x2_u32r = (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 11) * ((s32)bmp280_dev.calib_param.dig_P6);
v_x2_u32r = v_x2_u32r + ((v_x1_u32r * ((s32)bmp280_dev.calib_param.dig_P5)) << 1);
v_x2_u32r = (v_x2_u32r >> 2) + (((s32)bmp280_dev.calib_param.dig_P4) << 16);
/* 计算X1*/
v_x1_u32r = (((bmp280_dev.calib_param.dig_P3 * (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 13)) >> 3)
+ ((((s32)bmp280_dev.calib_param.dig_P2) * v_x1_u32r) >> 1)) >> 18;
v_x1_u32r = ((((32768 + v_x1_u32r)) * ((s32)bmp280_dev.calib_param.dig_P1)) >> 15);
/* 计算气压值 */
v_pressure_u32 = (((u32)(((s32)1048576) - uncomppres) - (v_x2_u32r >> 12))) * 3125;
/* 检查溢出 */
if (v_pressure_u32 < 0x80000000)
{
if (v_x1_u32r != 0)
v_pressure_u32 = (v_pressure_u32 << 1) / ((u32)v_x1_u32r);
else
return BMP280_INVALID_DATA;
} else {
if (v_x1_u32r != 0)
v_pressure_u32 = (v_pressure_u32 / (u32)v_x1_u32r) * 2;
else
return BMP280_INVALID_DATA;
}
/* 计算X1 */
v_x1_u32r = (((s32)bmp280_dev.calib_param.dig_P9) * ((s32)(((v_pressure_u32 >> 3)
* (v_pressure_u32 >> 3)) >> 13))) >> 12;
/* 计算X2*/
v_x2_u32r = (((s32)(v_pressure_u32 >> 2)) * ((s32)bmp280_dev.calib_param.dig_P8)) >> 13;
/* 计算真实的气压值*/
v_pressure_u32 = (u32)((s32)v_pressure_u32 + ((v_x1_u32r + v_x2_u32r
+ bmp280_dev.calib_param.dig_P7) >> 4));
return v_pressure_u32;
}

View File

@@ -0,0 +1,88 @@
#ifndef _BSP_BMP280_H
#define _BSP_BMP280_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_bmp280.h
作者 : 左忠凯
版本 : V1.0
描述 : BMP280驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/17 左忠凯创建
***************************************************************/
#include "bsp.h"
#include "bsp_gpio.h"
/* 宏定义 */
#define BMP280_CSN(n) (n ? gpio_pinwrite(GPIO1, 20, 1) : gpio_pinwrite(GPIO1, 20, 0)) //SPI片选信号
#define BMP280_ID_VALUE 0X58 /* BMP280 ID值 */
#define BMP280_RESET_VALUE 0XB6 /* BMP280复位值 */
/* BMP280寄存器宏定义 */
#define BMP280_TEMPXLSB_REG 0XFC /* 温度值的bit[3:0]寄存器 */
#define BMP280_TEMPLSB_REG 0XFB /* 温度值的bit[11:4]寄存器 */
#define BMP280_TEMPMSB_REG 0XFA /* 温度值的bit[19:12]寄存器 */
#define BMP280_PRESXLSB_REG 0XF9 /* 压力值的bit[3:0]寄存器 */
#define BMP280_PRESLSB_REG 0XF8 /* 压力值的bit[11:4]寄存器 */
#define BMP280_PRESMSB_REG 0XF7 /* 压力值的bit[19:12]寄存器 */
#define BMP280_CONFIG_REG 0XF5 /* 配置寄存器 */
#define BMP280_CTRLMEAS_REG 0XF4 /* 测量配置寄存器 */
#define BMP280_STATUS_REG 0XF3 /* 状态寄存器 */
#define BMP280_RESET_REG 0XE0 /* 复位寄存器 */
#define BMP280_ID_REG 0XD0 /* ID寄存器 */
#define BMP280_TRIMPARAM_FRG 0X88 /* 参数组寄存器首地址 */
#define BMP280_TRIMPARAM_LEN 24 /* 参数组寄存器长度 */
#define BMP280_INVALID_DATA 0 /* 无效的数据 */
/*
* BMP280 参数结构体
*/
struct bmp280_calib_param
{
unsigned short dig_T1; /* T1参数 */
short dig_T2; /* T2参数 */
short dig_T3; /* T3参数 */
unsigned short dig_P1; /* P1参数 */
short dig_P2; /* P2参数 */
short dig_P3; /* P3参数 */
short dig_P4; /* P4参数 */
short dig_P5; /* P5参数 */
short dig_P6; /* P6参数 */
short dig_P7; /* P7参数 */
short dig_P8; /* P8参数 */
short dig_P9; /* P9参数 */
signed int t_fine; /* t_fine参数*/
};
/*
* BMP280结构体
*/
struct bmp280_dev_struc
{
struct bmp280_calib_param calib_param;
signed int uncomp_temp; /* 原始的温度值 */
signed int uncomp_pres; /* 原始的压力值 */
signed int actual_temp; /* 真实的温度值 */
signed int actual_pres; /* 真实的压力值 */
};
extern struct bmp280_dev_struc bmp280_dev;
/* 函数声明 */
unsigned char bmp280_init(void);
unsigned char bmp280_read_reg(unsigned char reg);
void bmp280_read_len(unsigned char reg, unsigned char *buf, unsigned char len);
void bmp280_write_reg(unsigned char reg, unsigned char value);
void bmp280_get_calibparam(void);
signed int bmp280_get_uncomptemp(void);
signed int bmp280_get_uncomppres(void);
signed int bmp280_get_actualtemp(signed int uncomptemp);
unsigned int bmp280_get_actualpres(s32 uncomppres);
#endif

View File

@@ -0,0 +1,126 @@
#include "bsp_clk.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_clk.c
作者 : 左忠凯
版本 : V1.0
描述 : 系统时钟驱动。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凯创建
V2.0 2019/1/3 左忠凯修改
添加了函数imx6u_clkinit()完成I.MX6U的系统时钟初始化
V2.1 2019/3/1 左忠凯修改
添加UART时钟源配置代码
***************************************************************/
/*
* @description : 使能I.MX6U所有外设时钟
* @param : 无
* @return : 无
*/
void clk_enable(void)
{
CCM->CCGR0 = 0XFFFFFFFF;
CCM->CCGR1 = 0XFFFFFFFF;
CCM->CCGR2 = 0XFFFFFFFF;
CCM->CCGR3 = 0XFFFFFFFF;
CCM->CCGR4 = 0XFFFFFFFF;
CCM->CCGR5 = 0XFFFFFFFF;
CCM->CCGR6 = 0XFFFFFFFF;
}
/*
* @description : 初始化系统时钟设置系统时钟为528Mhz并且设置PLL2和PLL3各个
PFD时钟,所有的时钟频率均按照I.MX6U官方手册推荐的值.
* @param : 无
* @return : 无
*/
void imx6u_clkinit(void)
{
unsigned int reg = 0;
/* 1、设置ARM内核时钟为528MHz */
/* 1.1、判断当前ARM内核是使用的那个时钟源启动的正常情况下ARM内核是由pll1_sw_clk驱动的
* pll1_sw_clk有两个来源pll1_main_clk和tep_clk(参考手册648页)。
* 如果我们要让ARM内核跑到528M的话那必须选择pll1_main_clk作为pll1的时钟源。
* 如果我们要修改pll1_main_clk时钟的话就必须先将pll1_sw_clk从pll1_main_clk切换到step_clk,
* 当修改完pll1_main_clk以后在将pll1_sw_clk切换回pll1_main_clk。而step_clk的时钟源可以选择
* 板子上的24MHz晶振。
*/
if((((CCM->CCSR) >> 2) & 0x1 ) == 0) /* 当前pll1_sw_clk使用的pll1_main_clk*/
{
CCM->CCSR &= ~(1 << 8); /* 配置step_clk时钟源为24MH OSC */
CCM->CCSR |= (1 << 2); /* 配置pll1_sw_clk时钟源为step_clk */
}
/* 1.2、设置pll1_main_clk为1056MHz,也就是528*2=1056MHZ,
* 因为pll1_sw_clk进ARM内核的时候会被二分频
* 配置CCM_ANLOG->PLL_ARM寄存器
* bit13: 1 使能时钟输出
* bit[6:0]: 88, 由公式Fout = Fin * div_select / 2.01056=24*div_select/2.0,
* 得出div_select= 88
*/
CCM_ANALOG->PLL_ARM = (1 << 13) | ((88 << 0) & 0X7F); /* 配置pll1_main_clk=1056MHz */
CCM->CCSR &= ~(1 << 2); /* 将pll_sw_clk时钟重新切换回pll1_main_clk */
CCM->CACRR = 1; /* ARM内核时钟为pll1_sw_clk/2=1056/2=528Mhz */
/* 2、设置PLL2(SYS PLL)各个PFD */
reg = CCM_ANALOG->PFD_528;
reg &= ~(0X3F3F3F3F); /* 清除原来的设置 */
reg |= 32<<24; /* PLL2_PFD3=528*18/32=297Mhz */
reg |= 24<<16; /* PLL2_PFD2=528*18/24=396Mhz(DDR使用的时钟最大400Mhz) */
reg |= 16<<8; /* PLL2_PFD1=528*18/16=594Mhz */
reg |= 27<<0; /* PLL2_PFD0=528*18/27=352Mhz */
CCM_ANALOG->PFD_528=reg; /* 设置PLL2_PFD0~3 */
/* 3、设置PLL3(USB1)各个PFD */
reg = 0; /* 清零 */
reg = CCM_ANALOG->PFD_480;
reg &= ~(0X3F3F3F3F); /* 清除原来的设置 */
reg |= 19<<24; /* PLL3_PFD3=480*18/19=454.74Mhz */
reg |= 17<<16; /* PLL3_PFD2=480*18/17=508.24Mhz */
reg |= 16<<8; /* PLL3_PFD1=480*18/16=540Mhz */
reg |= 12<<0; /* PLL3_PFD0=480*18/12=720Mhz */
CCM_ANALOG->PFD_480=reg; /* 设置PLL3_PFD0~3 */
/* 4、设置AHB时钟 最小6Mhz 最大132Mhz (boot rom自动设置好了可以不用设置)*/
CCM->CBCMR &= ~(3 << 18); /* 清除设置*/
CCM->CBCMR |= (1 << 18); /* pre_periph_clk=PLL2_PFD2=396MHz */
CCM->CBCDR &= ~(1 << 25); /* periph_clk=pre_periph_clk=396MHz */
while(CCM->CDHIPR & (1 << 5));/* 等待握手完成 */
/* 修改AHB_PODF位的时候需要先禁止AHB_CLK_ROOT的输出但是
* 我没有找到关闭AHB_CLK_ROOT输出的的寄存器所以就没法设置。
* 下面设置AHB_PODF的代码仅供学习参考不能直接拿来使用
* 内部boot rom将AHB_PODF设置为了3分频即使我们不设置AHB_PODF
* AHB_ROOT_CLK也依旧等于396/3=132Mhz。
*/
#if 0
/* 要先关闭AHB_ROOT_CLK输出否则时钟设置会出错 */
CCM->CBCDR &= ~(7 << 10); /* CBCDR的AHB_PODF清零 */
CCM->CBCDR |= 2 << 10; /* AHB_PODF 3分频AHB_CLK_ROOT=132MHz */
while(CCM->CDHIPR & (1 << 1));/
* 等待握手完成 */
#endif
/* 5、设置IPG_CLK_ROOT最小3Mhz最大66Mhz (boot rom自动设置好了可以不用设置)*/
CCM->CBCDR &= ~(3 << 8); /* CBCDR的IPG_PODF清零 */
CCM->CBCDR |= 1 << 8; /* IPG_PODF 2分频IPG_CLK_ROOT=66MHz */
/* 6、设置PERCLK_CLK_ROOT时钟 */
CCM->CSCMR1 &= ~(1 << 6); /* PERCLK_CLK_ROOT时钟源为IPG */
CCM->CSCMR1 &= ~(7 << 0); /* PERCLK_PODF位清零即1分频 */
/* 设置UART时钟源频率为80M */
CCM->CSCDR1 &= ~(1 << 6); /* UART时钟源为pll3_80m */
CCM->CSCDR1 &= ~0X3F; /* UART时钟1分频 */
#if 0
/* 设置ECSPI时钟源为60Mhz */
CCM->CSCDR2 &= ~(1 << 18); /* ECSPI时钟源为pll3_60m*/
CCM->CSCDR2 &= ~(0X3F << 19); /* ECSPI 1分频 */
#endif
}

View File

@@ -0,0 +1,21 @@
#ifndef __BSP_CLK_H
#define __BSP_CLK_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_clk.h
作者 : 左忠凯
版本 : V1.0
描述 : 系统时钟驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 函数声明 */
void clk_enable(void);
void imx6u_clkinit(void);
#endif

View File

@@ -0,0 +1,180 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_delay.c
作者 : 左忠凯
版本 : V1.0
描述 : 延时文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
V2.0 2019/1/15 左忠凯修改
使用定时器GPT实现高精度延时,添加了:
delay_init 延时初始化函数
gpt1_irqhandler gpt1定时器中断处理函数
delayus us延时函数
delayms ms延时函数
***************************************************************/
#include "bsp_delay.h"
/*
* @description : 延时有关硬件初始化,主要是GPT定时器
GPT定时器时钟源选择ipg_clk=66Mhz
* @param : 无
* @return : 无
*/
void delay_init(void)
{
GPT1->CR = 0; /* 清零bit0也为0即停止GPT */
GPT1->CR = 1 << 15; /* bit15置1进入软复位 */
while((GPT1->CR >> 15) & 0x01); /*等待复位完成 */
/*
* GPT的CR寄存器,GPT通用设置
* bit22:20 000 输出比较1的输出功能关闭也就是对应的引脚没反应
* bit9: 0 Restart模式,当CNT等于OCR1的时候就产生中断
* bit8:6 001 GPT时钟源选择ipg_clk=66Mhz
* bit
*/
GPT1->CR = (1<<6);
/*
* GPT的PR寄存器GPT的分频设置
* bit11:0 设置分频值设置为0表示1分频
* 以此类推最大可以设置为0XFFF也就是最大4096分频
*/
GPT1->PR = 65; /* 设置为65即66分频因此GPT1时钟为66M/(65+1)=1MHz */
/*
* GPT的OCR1寄存器GPT的输出比较1比较计数值
* GPT的时钟为1Mz那么计数器每计一个值就是就是1us。
* 为了实现较大的计数我们将比较值设置为最大的0XFFFFFFFF,
* 这样一次计满就是0XFFFFFFFFus = 4294967296us = 4295s = 71.5min
* 也就是说一次计满最多71.5分钟,存在溢出
*/
GPT1->OCR[0] = 0XFFFFFFFF;
GPT1->CR |= 1<<0; //使能GPT1
/* 一下屏蔽的代码是GPT定时器中断代码
* 如果想学习GPT定时器的话可以参考一下代码。
*/
#if 0
/*
* GPT的PR寄存器GPT的分频设置
* bit11:0 设置分频值设置为0表示1分频
* 以此类推最大可以设置为0XFFF也就是最大4096分频
*/
GPT1->PR = 65; //设置为1即65+1=66分频因此GPT1时钟为66M/66=1MHz
/*
* GPT的OCR1寄存器GPT的输出比较1比较计数值
* 当GPT的计数值等于OCR1里面值时候输出比较1就会发生中断
* 这里定时500ms产生中断因此就应该为1000000/2=500000;
*/
GPT1->OCR[0] = 500000;
/*
* GPT的IR寄存器使能通道1的比较中断
* bit0 0 使能输出比较中断
*/
GPT1->IR |= 1 << 0;
/*
* 使能GIC里面相应的中断并且注册中断处理函数
*/
GIC_EnableIRQ(GPT1_IRQn); //使能GIC中对应的中断
system_register_irqhandler(GPT1_IRQn, (system_irq_handler_t)gpt1_irqhandler, NULL); //注册中断服务函数
#endif
}
#if 0
/* 中断处理函数 */
void gpt1_irqhandler(void)
{
static unsigned char state = 0;
state = !state;
/*
* GPT的SR寄存器状态寄存器
* bit2 1 输出比较1发生中断
*/
if(GPT1->SR & (1<<0))
{
led_switch(LED2, state);
}
GPT1->SR |= 1<<0; /* 清除中断标志位 */
}
#endif
/*
* @description : 微秒(us)级延时
* @param - value : 需要延时的us数,最大延时0XFFFFFFFFus
* @return : 无
*/
void delayus(unsigned int usdelay)
{
unsigned long oldcnt,newcnt;
unsigned long tcntvalue = 0; /* 走过的总时间 */
oldcnt = GPT1->CNT;
while(1)
{
newcnt = GPT1->CNT;
if(newcnt != oldcnt)
{
if(newcnt > oldcnt) /* GPT是向上计数器,并且没有溢出 */
tcntvalue += newcnt - oldcnt;
else /* 发生溢出 */
tcntvalue += 0XFFFFFFFF-oldcnt + newcnt;
oldcnt = newcnt;
if(tcntvalue >= usdelay)/* 延时时间到了 */
break; /* 跳出 */
}
}
}
/*
* @description : 毫秒(ms)级延时
* @param - msdelay : 需要延时的ms数
* @return : 无
*/
void delayms(unsigned int msdelay)
{
int i = 0;
for(i=0; i<msdelay; i++)
{
delayus(1000);
}
}
/*
* @description : 短时间延时函数
* @param - n : 要延时循环次数(空操作循环次数,模式延时)
* @return : 无
*/
void delay_short(volatile unsigned int n)
{
while(n--){}
}
/*
* @description : 延时函数,在396Mhz的主频下
* 延时时间大约为1ms
* @param - n : 要延时的ms数
* @return : 无
*/
void delay(volatile unsigned int n)
{
while(n--)
{
delay_short(0x7ff);
}
}

View File

@@ -0,0 +1,27 @@
#ifndef __BSP_DELAY_H
#define __BSP_DELAY_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_delay.h
作者 : 左忠凯
版本 : V1.0
描述 : 延时头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
V2.0 2019/1/15 左忠凯修改
添加了一些函数声明。
***************************************************************/
#include "bsp.h"
/* 函数声明 */
void delay_init(void);
void delayus(unsigned int usdelay);
void delayms(unsigned int msdelay);
void delay(volatile unsigned int n);
void gpt1_irqhandler(void);
#endif

View File

@@ -0,0 +1,77 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_epittimer.c
作者 : 左忠凯
版本 : V1.0
描述 : EPIT定时器驱动文件。
其他 : 配置EPIT定时器实现EPIT定时器中断处理函数
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
#include "bsp_epittimer.h"
#include "bsp_int.h"
#include "bsp_led.h"
#include "tos_k.h"
/*
* @description : 初始化EPIT定时器.
* EPIT定时器是32位向下计数器,时钟源使用ipg=66Mhz
* @param - frac : 分频值范围为0~4095分别对应1~4096分频。
* @param - value : 倒计数值。
* @return : 无
*/
void epit1_init(unsigned int frac, unsigned int value)
{
if(frac > 0XFFF)
frac = 0XFFF;
EPIT1->CR = 0; /* 先清零CR寄存器 */
/*
* CR寄存器:
* bit25:24 01 时钟源选择Peripheral clock=66MHz
* bit15:4 frac 分频值
* bit3: 1 当计数器到0的话从LR重新加载数值
* bit2: 1 比较中断使能
* bit1: 1 初始计数值来源于LR寄存器值
* bit0: 0 先关闭EPIT1
*/
EPIT1->CR = (1<<24 | frac << 4 | 1<<3 | 1<<2 | 1<<1);
EPIT1->LR = value; /* 倒计数值 */
EPIT1->CMPR = 0; /* 比较寄存器,当计数器值和此寄存器值相等的话就会产生中断 */
/* 使能GIC中对应的中断 */
GIC_EnableIRQ(EPIT1_IRQn);
/* 注册中断服务函数 */
#if 0
system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)epit1_irqhandler, NULL);
#else
tos_interrupt_handler_register(EPIT1_IRQn, (int_handler_t)epit1_irqhandler, NULL);
#endif
EPIT1->CR |= 1<<0; /* 使能EPIT1 */
}
/*
* @description : EPIT中断处理函数
* @param : 无
* @return : 无
*/
void epit1_irqhandler(void *arg)
{
static unsigned char state = 0;
printf("######\r\n");
state = !state;
if(EPIT1->SR & (1<<0)) /* 判断比较事件发生 */
{
led_switch(LED0, state); /* 定时器周期到反转LED */
}
EPIT1->SR |= 1<<0; /* 清除中断标志位 */
}

View File

@@ -0,0 +1,20 @@
#ifndef _BSP_EPITTIMER_H
#define _BSP_EPITTIMER_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_epittimer.h
作者 : 左忠凯
版本 : V1.0
描述 : EPIT定时器驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 函数声明 */
void epit1_init(unsigned int frac, unsigned int value);
void epit1_irqhandler(void *arg);
#endif

View File

@@ -0,0 +1,71 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_exit.c
作者 : 左忠凯
版本 : V1.0
描述 : 外部中断驱动。
其他 : 配置按键对应的GPIP为中断模式
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp_exit.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
#include "bsp_beep.h"
#include "bsp_int.h"
#include "tos_k.h"
/*
* @description : 初始化外部中断
* @param : 无
* @return : 无
*/
void exit_init(void)
{
gpio_pin_config_t key_config;
/* 1、设置IO复用 */
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0); /* 复用为GPIO1_IO18 */
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
/* 2、初始化GPIO为中断模式 */
key_config.direction = kGPIO_DigitalInput;
key_config.interruptMode = kGPIO_IntFallingEdge;
key_config.outputLogic = 1;
gpio_init(GPIO1, 18, &key_config);
GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /* 使能GIC中对应的中断 */
#if 0
system_register_irqhandler(GPIO1_Combined_16_31_IRQn, (system_irq_handler_t)gpio1_io18_irqhandler, NULL); /* 注册中断服务函数 */
#else
tos_interrupt_handler_register(GPIO1_Combined_16_31_IRQn, (int_handler_t)gpio1_io18_irqhandler, NULL);
#endif
gpio_enableint(GPIO1, 18); /* 使能GPIO1_IO18的中断功能 */
}
/*
* @description : GPIO1_IO18最终的中断处理函数
* @param : 无
* @return : 无
*/
void gpio1_io18_irqhandler(void *arg)
{
static unsigned char state = 0;
/*
*采用延时消抖,中断服务函数中禁止使用延时函数!因为中断服务需要
*快进快出!!这里为了演示所以采用了延时函数进行消抖,后面我们会讲解
*定时器中断消抖法!!!
*/
delay(10);
if (gpio_pinread(GPIO1, 18) == 0) /* 按键按下了 */
{
state = !state;
beep_switch(state);
}
gpio_clearintflags(GPIO1, 18); /* 清除中断标志位 */
}

View File

@@ -0,0 +1,19 @@
#ifndef _BSP_EXIT_H
#define _BSP_EXIT_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_exit.c
作者 : 左忠凯
版本 : V1.0
描述 : 外部中断驱动头文件。
其他 : 配置按键对应的GPIP为中断模式
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 函数声明 */
void exit_init(void); /* 中断初始化 */
void gpio1_io18_irqhandler(void *arg); /* 中断处理函数 */
#endif

View File

@@ -0,0 +1,153 @@
#include "bsp_gpio.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_gpio.h
作者 : 左忠凯
版本 : V1.0
描述 : GPIO操作文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
V2.0 2019/1/4 左忠凯修改:
修改gpio_init()函数,支持中断配置.
添加gpio_intconfig()函数,初始化中断
添加gpio_enableint()函数,使能中断
添加gpio_clearintflags()函数,清除中断标志位
***************************************************************/
/*
* @description : GPIO初始化。
* @param - base : 要初始化的GPIO组。
* @param - pin : 要初始化GPIO在组内的编号。
* @param - config : GPIO配置结构体。
* @return : 无
*/
void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config)
{
base->IMR &= ~(1U << pin);
if(config->direction == kGPIO_DigitalInput) /* GPIO作为输入 */
{
base->GDIR &= ~( 1 << pin);
}
else /* 输出 */
{
base->GDIR |= 1 << pin;
gpio_pinwrite(base,pin, config->outputLogic); /* 设置默认输出电平 */
}
gpio_intconfig(base, pin, config->interruptMode); /* 中断功能配置 */
}
/*
* @description : 读取指定GPIO的电平值 。
* @param - base : 要读取的GPIO组。
* @param - pin : 要读取的GPIO脚号。
* @return : 无
*/
int gpio_pinread(GPIO_Type *base, int pin)
{
return (((base->DR) >> pin) & 0x1);
}
/*
* @description : 指定GPIO输出高或者低电平 。
* @param - base : 要输出的的GPIO组。
* @param - pin : 要输出的GPIO脚号。
* @param - value : 要输出的电平1 输出高电平, 0 输出低低电平
* @return : 无
*/
void gpio_pinwrite(GPIO_Type *base, int pin, int value)
{
if (value == 0U)
{
base->DR &= ~(1U << pin); /* 输出低电平 */
}
else
{
base->DR |= (1U << pin); /* 输出高电平 */
}
}
/*
* @description : 设置GPIO的中断配置功能
* @param - base : 要配置的IO所在的GPIO组。
* @param - pin : 要配置的GPIO脚号。
* @param - pinInterruptMode: 中断模式参考枚举类型gpio_interrupt_mode_t
* @return : 无
*/
void gpio_intconfig(GPIO_Type* base, unsigned int pin, gpio_interrupt_mode_t pin_int_mode)
{
volatile uint32_t *icr;
uint32_t icrShift;
icrShift = pin;
base->EDGE_SEL &= ~(1U << pin);
if(pin < 16) /* 低16位 */
{
icr = &(base->ICR1);
}
else /* 高16位 */
{
icr = &(base->ICR2);
icrShift -= 16;
}
switch(pin_int_mode)
{
case(kGPIO_IntLowLevel):
*icr &= ~(3U << (2 * icrShift));
break;
case(kGPIO_IntHighLevel):
*icr = (*icr & (~(3U << (2 * icrShift)))) | (1U << (2 * icrShift));
break;
case(kGPIO_IntRisingEdge):
*icr = (*icr & (~(3U << (2 * icrShift)))) | (2U << (2 * icrShift));
break;
case(kGPIO_IntFallingEdge):
*icr |= (3U << (2 * icrShift));
break;
case(kGPIO_IntRisingOrFallingEdge):
base->EDGE_SEL |= (1U << pin);
break;
default:
break;
}
}
/*
* @description : 使能GPIO的中断功能
* @param - base : 要使能的IO所在的GPIO组。
* @param - pin : 要使能的GPIO在组内的编号。
* @return : 无
*/
void gpio_enableint(GPIO_Type* base, unsigned int pin)
{
base->IMR |= (1 << pin);
}
/*
* @description : 禁止GPIO的中断功能
* @param - base : 要禁止的IO所在的GPIO组。
* @param - pin : 要禁止的GPIO在组内的编号。
* @return : 无
*/
void gpio_disableint(GPIO_Type* base, unsigned int pin)
{
base->IMR &= ~(1 << pin);
}
/*
* @description : 清除中断标志位(写1清除)
* @param - base : 要清除的IO所在的GPIO组。
* @param - pin : 要清除的GPIO掩码。
* @return : 无
*/
void gpio_clearintflags(GPIO_Type* base, unsigned int pin)
{
base->ISR |= (1 << pin);
}

View File

@@ -0,0 +1,61 @@
#ifndef _BSP_GPIO_H
#define _BSP_GPIO_H
#define _BSP_KEY_H
#include "bsp.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_gpio.h
作者 : 左忠凯
版本 : V1.0
描述 : GPIO操作文件头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
V2.0 2019/1/4 左忠凯修改
添加GPIO中断相关定义
***************************************************************/
/*
* 枚举类型和结构体定义
*/
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /* 输入 */
kGPIO_DigitalOutput = 1U, /* 输出 */
} gpio_pin_direction_t;
/*
* GPIO中断触发类型枚举
*/
typedef enum _gpio_interrupt_mode
{
kGPIO_NoIntmode = 0U, /* 无中断功能 */
kGPIO_IntLowLevel = 1U, /* 低电平触发 */
kGPIO_IntHighLevel = 2U, /* 高电平触发 */
kGPIO_IntRisingEdge = 3U, /* 上升沿触发 */
kGPIO_IntFallingEdge = 4U, /* 下降沿触发 */
kGPIO_IntRisingOrFallingEdge = 5U, /* 上升沿和下降沿都触发 */
} gpio_interrupt_mode_t;
/*
* GPIO配置结构体
*/
typedef struct _gpio_pin_config
{
gpio_pin_direction_t direction; /* GPIO方向:输入还是输出 */
uint8_t outputLogic; /* 如果是输出的话,默认输出电平 */
gpio_interrupt_mode_t interruptMode; /* 中断方式 */
} gpio_pin_config_t;
/* 函数声明 */
void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config);
int gpio_pinread(GPIO_Type *base, int pin);
void gpio_pinwrite(GPIO_Type *base, int pin, int value);
void gpio_intconfig(GPIO_Type* base, unsigned int pin, gpio_interrupt_mode_t pinInterruptMode);
void gpio_enableint(GPIO_Type* base, unsigned int pin);
void gpio_disableint(GPIO_Type* base, unsigned int pin);
void gpio_clearintflags(GPIO_Type* base, unsigned int pin);
#endif

View File

@@ -0,0 +1,315 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_i2c.c
作者 : 左忠凯
版本 : V1.0
描述 : IIC驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
#include "bsp_i2c.h"
#include "bsp_delay.h"
#include "printf.h"
/*
* @description : 初始化I2C波特率100KHZ
* @param - base : 要初始化的IIC设置
* @return : 无
*/
void i2c_init(I2C_Type *base)
{
/* 1、配置I2C */
base->I2CR &= ~(1 << 7); /* 要访问I2C的寄存器首先需要先关闭I2C */
/* 设置波特率为100K
* I2C的时钟源来源于IPG_CLK_ROOT=66Mhz
* IC2 时钟 = PERCLK_ROOT/dividison(IFDR寄存器)
* 设置寄存器IFDR,IFDR寄存器参考IMX6UL参考手册P1260页表29-3
* 根据表29-3里面的值挑选出一个还是的分频数比如本例程我们
* 设置I2C的波特率为100K 因此当分频值=66000000/100000=660.
* 在表29-3里面查找没有660这个值但是有640因此就用640,
* 即寄存器IFDR的IC位设置为0X15
*/
base->IFDR = 0X15 << 0;
/*
* 设置寄存器I2CR开启I2C
* bit[7] : 1 使能I2C,I2CR寄存器其他位其作用之前此位必须最先置1
*/
base->I2CR |= (1<<7);
}
/*
* @description : 发送重新开始信号
* @param - base : 要使用的IIC
* @param - addrss : 设备地址
* @param - direction : 方向
* @return : 0 正常 其他值 出错
*/
unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
/* I2C忙并且工作在从模式,跳出 */
if(base->I2SR & (1 << 5) && (((base->I2CR) & (1 << 5)) == 0))
return 1;
/*
* 设置寄存器I2CR
* bit[4]: 1 发送
* bit[2]: 1 产生重新开始信号
*/
base->I2CR |= (1 << 4) | (1 << 2);
/*
* 设置寄存器I2DR
* bit[7:0] : 要发送的数据,这里写入从设备地址
* 参考资料:IMX6UL参考手册P1249
*/
base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
return 0;
}
/*
* @description : 发送开始信号
* @param - base : 要使用的IIC
* @param - addrss : 设备地址
* @param - direction : 方向
* @return : 0 正常 其他值 出错
*/
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
if(base->I2SR & (1 << 5)) /* I2C忙 */
return 1;
/*
* 设置寄存器I2CR
* bit[5]: 1 主模式
* bit[4]: 1 发送
*/
base->I2CR |= (1 << 5) | (1 << 4);
/*
* 设置寄存器I2DR
* bit[7:0] : 要发送的数据,这里写入从设备地址
* 参考资料:IMX6UL参考手册P1249
*/
base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
return 0;
}
/*
* @description : 检查并清除错误
* @param - base : 要使用的IIC
* @param - status : 状态
* @return : 状态结果
*/
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status)
{
/* 检查是否发生仲裁丢失错误 */
if(status & (1<<4))
{
base->I2SR &= ~(1<<4); /* 清除仲裁丢失错误位 */
base->I2CR &= ~(1 << 7); /* 先关闭I2C */
base->I2CR |= (1 << 7); /* 重新打开I2C */
return I2C_STATUS_ARBITRATIONLOST;
}
else if(status & (1 << 0)) /* 没有接收到从机的应答信号 */
{
return I2C_STATUS_NAK; /* 返回NAK(No acknowledge) */
}
return I2C_STATUS_OK;
}
/*
* @description : 停止信号
* @param - base : 要使用的IIC
* @param : 无
* @return : 状态结果
*/
unsigned char i2c_master_stop(I2C_Type *base)
{
unsigned short timeout = 0xffff;
/*
* 清除I2CR的bit[5:3]这三位
*/
base->I2CR &= ~((1 << 5) | (1 << 4) | (1 << 3));
/* 等待忙结束 */
while((base->I2SR & (1 << 5)))
{
timeout--;
if(timeout == 0) /* 超时跳出 */
return I2C_STATUS_TIMEOUT;
}
return I2C_STATUS_OK;
}
/*
* @description : 发送数据
* @param - base : 要使用的IIC
* @param - buf : 要发送的数据
* @param - size : 要发送的数据大小
* @param - flags : 标志
* @return : 无
*/
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size)
{
/* 等待传输完成 */
while(!(base->I2SR & (1 << 7)));
base->I2SR &= ~(1 << 1); /* 清除标志位 */
base->I2CR |= 1 << 4; /* 发送数据 */
while(size--)
{
base->I2DR = *buf++; /* 将buf中的数据写入到I2DR寄存器 */
while(!(base->I2SR & (1 << 1))); /* 等待传输完成 */
base->I2SR &= ~(1 << 1); /* 清除标志位 */
/* 检查ACK */
if(i2c_check_and_clear_error(base, base->I2SR))
break;
}
base->I2SR &= ~(1 << 1);
i2c_master_stop(base); /* 发送停止信号 */
}
/*
* @description : 读取数据
* @param - base : 要使用的IIC
* @param - buf : 读取到数据
* @param - size : 要读取的数据大小
* @return : 无
*/
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size)
{
volatile uint8_t dummy = 0;
dummy++; /* 防止编译报错 */
/* 等待传输完成 */
while(!(base->I2SR & (1 << 7)));
base->I2SR &= ~(1 << 1); /* 清除中断挂起位 */
base->I2CR &= ~((1 << 4) | (1 << 3)); /* 接收数据 */
/* 如果只接收一个字节数据的话发送NACK信号 */
if(size == 1)
base->I2CR |= (1 << 3);
dummy = base->I2DR; /* 假读 */
while(size--)
{
while(!(base->I2SR & (1 << 1))); /* 等待传输完成 */
base->I2SR &= ~(1 << 1); /* 清除标志位 */
if(size == 0)
{
i2c_master_stop(base); /* 发送停止信号 */
}
if(size == 1)
{
base->I2CR |= (1 << 3);
}
*buf++ = base->I2DR;
}
}
/*
* @description : I2C数据传输包括读和写
* @param - base: 要使用的IIC
* @param - xfer: 传输结构体
* @return : 传输结果,0 成功,其他值 失败;
*/
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer)
{
unsigned char ret = 0;
enum i2c_direction direction = xfer->direction;
base->I2SR &= ~((1 << 1) | (1 << 4)); /* 清除标志位 */
/* 等待传输完成 */
while(!((base->I2SR >> 7) & 0X1)){};
/* 如果是读的话,要先发送寄存器地址,所以要先将方向改为写 */
if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
{
direction = kI2C_Write;
}
ret = i2c_master_start(base, xfer->slaveAddress, direction); /* 发送开始信号 */
if(ret)
{
return ret;
}
while(!(base->I2SR & (1 << 1))){}; /* 等待传输完成 */
ret = i2c_check_and_clear_error(base, base->I2SR); /* 检查是否出现传输错误 */
if(ret)
{
i2c_master_stop(base); /* 发送出错,发送停止信号 */
return ret;
}
/* 发送寄存器地址 */
if(xfer->subaddressSize)
{
do
{
base->I2SR &= ~(1 << 1); /* 清除标志位 */
xfer->subaddressSize--; /* 地址长度减一 */
base->I2DR = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); //向I2DR寄存器写入子地址
while(!(base->I2SR & (1 << 1))); /* 等待传输完成 */
/* 检查是否有错误发生 */
ret = i2c_check_and_clear_error(base, base->I2SR);
if(ret)
{
i2c_master_stop(base); /* 发送停止信号 */
return ret;
}
} while ((xfer->subaddressSize > 0) && (ret == I2C_STATUS_OK));
if(xfer->direction == kI2C_Read) /* 读取数据 */
{
base->I2SR &= ~(1 << 1); /* 清除中断挂起位 */
i2c_master_repeated_start(base, xfer->slaveAddress, kI2C_Read); /* 发送重复开始信号和从机地址 */
while(!(base->I2SR & (1 << 1))){};/* 等待传输完成 */
/* 检查是否有错误发生 */
ret = i2c_check_and_clear_error(base, base->I2SR);
if(ret)
{
ret = I2C_STATUS_ADDRNAK;
i2c_master_stop(base); /* 发送停止信号 */
return ret;
}
}
}
/* 发送数据 */
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
{
i2c_master_write(base, xfer->data, xfer->dataSize);
}
/* 读取数据 */
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
{
i2c_master_read(base, xfer->data, xfer->dataSize);
}
return 0;
}

View File

@@ -0,0 +1,61 @@
#ifndef _BSP_I2C_H
#define _BSP_I2C_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_i2c.c
作者 : 左忠凯
版本 : V1.0
描述 : IIC驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 相关宏定义 */
#define I2C_STATUS_OK (0)
#define I2C_STATUS_BUSY (1)
#define I2C_STATUS_IDLE (2)
#define I2C_STATUS_NAK (3)
#define I2C_STATUS_ARBITRATIONLOST (4)
#define I2C_STATUS_TIMEOUT (5)
#define I2C_STATUS_ADDRNAK (6)
/*
* I2C方向枚举类型
*/
enum i2c_direction
{
kI2C_Write = 0x0, /* 主机向从机写数据 */
kI2C_Read = 0x1, /* 主机从从机读数据 */
} ;
/*
* 主机传输结构体
*/
struct i2c_transfer
{
unsigned char slaveAddress; /* 7位从机地址 */
enum i2c_direction direction; /* 传输方向 */
unsigned int subaddress; /* 寄存器地址 */
unsigned char subaddressSize; /* 寄存器地址长度 */
unsigned char *volatile data; /* 数据缓冲区 */
volatile unsigned int dataSize; /* 数据缓冲区长度 */
};
/*
*函数声明
*/
void i2c_init(I2C_Type *base);
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status);
unsigned char i2c_master_stop(I2C_Type *base);
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size);
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size);
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer);
#endif

View File

@@ -0,0 +1,241 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_icm20608.c
作者 : 左忠凯
版本 : V1.0
描述 : ICM20608驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/3/26 左忠凯创建
***************************************************************/
#include "bsp_icm20608.h"
#include "bsp_delay.h"
#include "bsp_spi.h"
#include "printf.h"
struct icm20608_dev_struc icm20608_dev; /* icm20608设备 */
/*
* @description : 初始化ICM20608
* @param : 无
* @return : 0 初始化成功,其他值 初始化失败
*/
unsigned char icm20608_init(void)
{
unsigned char regvalue;
gpio_pin_config_t cs_config;
/* 1、ESPI3 IO初始化
* ECSPI3_SCLK -> UART2_RXD
* ECSPI3_MISO -> UART2_RTS
* ECSPI3_MOSI -> UART2_CTS
*/
IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0);
IOMUXC_SetPinMux(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0);
IOMUXC_SetPinMux(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0);
/* 配置SPI SCLK MISO MOSI IO属性
*bit 16: 0 HYS关闭
*bit [15:14]: 00 默认100K下拉
*bit [13]: 0 keeper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 驱动能力为R0/6
*bit [0]: 1 高转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0x10B1);
IOMUXC_SetPinConfig(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0x10B1);
IOMUXC_SetPinConfig(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0x10B1);
IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0);
IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0X10B0);
cs_config.direction = kGPIO_DigitalOutput;
cs_config.outputLogic = 0;
gpio_init(GPIO1, 20, &cs_config);
/* 2、初始化SPI */
spi_init(ECSPI3);
icm20608_write_reg(ICM20_PWR_MGMT_1, 0x80); /* 复位复位后为0x40,睡眠模式 */
delayms(50);
icm20608_write_reg(ICM20_PWR_MGMT_1, 0x01); /* 关闭睡眠,自动选择时钟 */
delayms(50);
regvalue = icm20608_read_reg(ICM20_WHO_AM_I);
printf("icm20608 id = %#X\r\n", regvalue);
if(regvalue != ICM20608G_ID && regvalue != ICM20608D_ID)
return 1;
icm20608_write_reg(ICM20_SMPLRT_DIV, 0x00); /* 输出速率是内部采样率 */
icm20608_write_reg(ICM20_GYRO_CONFIG, 0x18); /* 陀螺仪±2000dps量程 */
icm20608_write_reg(ICM20_ACCEL_CONFIG, 0x18); /* 加速度计±16G量程 */
icm20608_write_reg(ICM20_CONFIG, 0x04); /* 陀螺仪低通滤波BW=20Hz */
icm20608_write_reg(ICM20_ACCEL_CONFIG2, 0x04); /* 加速度计低通滤波BW=21.2Hz */
icm20608_write_reg(ICM20_PWR_MGMT_2, 0x00); /* 打开加速度计和陀螺仪所有轴 */
icm20608_write_reg(ICM20_LP_MODE_CFG, 0x00); /* 关闭低功耗 */
icm20608_write_reg(ICM20_FIFO_EN, 0x00); /* 关闭FIFO */
return 0;
}
/*
* @description : 写ICM20608指定寄存器
* @param - reg : 要读取的寄存器地址
* @param - value: 要写入的值
* @return : 无
*/
void icm20608_write_reg(unsigned char reg, unsigned char value)
{
/* ICM20608在使用SPI接口的时候寄存器地址
* 只有低7位有效,寄存器地址最高位是读/写标志位
* 读的时候要为1写的时候要为0。
*/
reg &= ~0X80;
ICM20608_CSN(0); /* 使能SPI传输 */
spich0_readwrite_byte(ECSPI3, reg); /* 发送寄存器地址 */
spich0_readwrite_byte(ECSPI3, value); /* 发送要写入的值 */
ICM20608_CSN(1); /* 禁止SPI传输 */
}
/*
* @description : 读取ICM20608寄存器值
* @param - reg : 要读取的寄存器地址
* @return : 读取到的寄存器值
*/
unsigned char icm20608_read_reg(unsigned char reg)
{
unsigned char reg_val;
/* ICM20608在使用SPI接口的时候寄存器地址
* 只有低7位有效,寄存器地址最高位是读/写标志位
* 读的时候要为1写的时候要为0。
*/
reg |= 0x80;
ICM20608_CSN(0); /* 使能SPI传输 */
spich0_readwrite_byte(ECSPI3, reg); /* 发送寄存器地址 */
reg_val = spich0_readwrite_byte(ECSPI3, 0XFF); /* 读取寄存器的值 */
ICM20608_CSN(1); /* 禁止SPI传输 */
return(reg_val); /* 返回读取到的寄存器值 */
}
/*
* @description : 读取ICM20608连续多个寄存器
* @param - reg : 要读取的寄存器地址
* @return : 读取到的寄存器值
*/
void icm20608_read_len(unsigned char reg, unsigned char *buf, unsigned char len)
{
unsigned char i;
/* ICM20608在使用SPI接口的时候寄存器地址只有低7位有效,
* 寄存器地址最高位是读/写标志位读的时候要为1写的时候要为0。
*/
reg |= 0x80;
ICM20608_CSN(0); /* 使能SPI传输 */
spich0_readwrite_byte(ECSPI3, reg); /* 发送寄存器地址 */
for(i = 0; i < len; i++) /* 顺序读取寄存器的值 */
{
buf[i] = spich0_readwrite_byte(ECSPI3, 0XFF);
}
ICM20608_CSN(1); /* 禁止SPI传输 */
}
/*
* @description : 获取陀螺仪的分辨率
* @param : 无
* @return : 获取到的分辨率
*/
float icm20608_gyro_scaleget(void)
{
unsigned char data;
float gyroscale;
data = (icm20608_read_reg(ICM20_GYRO_CONFIG) >> 3) & 0X3;
switch(data) {
case 0:
gyroscale = 131;
break;
case 1:
gyroscale = 65.5;
break;
case 2:
gyroscale = 32.8;
break;
case 3:
gyroscale = 16.4;
break;
}
return gyroscale;
}
/*
* @description : 获取加速度计的分辨率
* @param : 无
* @return : 获取到的分辨率
*/
unsigned short icm20608_accel_scaleget(void)
{
unsigned char data;
unsigned short accelscale;
data = (icm20608_read_reg(ICM20_ACCEL_CONFIG) >> 3) & 0X3;
switch(data) {
case 0:
accelscale = 16384;
break;
case 1:
accelscale = 8192;
break;
case 2:
accelscale = 4096;
break;
case 3:
accelscale = 2048;
break;
}
return accelscale;
}
/*
* @description : 读取ICM20608的加速度、陀螺仪和温度原始值
* @param : 无
* @return : 无
*/
void icm20608_getdata(void)
{
float gyroscale;
unsigned short accescale;
unsigned char data[14];
icm20608_read_len(ICM20_ACCEL_XOUT_H, data, 14);
gyroscale = icm20608_gyro_scaleget();
accescale = icm20608_accel_scaleget();
icm20608_dev.accel_x_adc = (signed short)((data[0] << 8) | data[1]);
icm20608_dev.accel_y_adc = (signed short)((data[2] << 8) | data[3]);
icm20608_dev.accel_z_adc = (signed short)((data[4] << 8) | data[5]);
icm20608_dev.temp_adc = (signed short)((data[6] << 8) | data[7]);
icm20608_dev.gyro_x_adc = (signed short)((data[8] << 8) | data[9]);
icm20608_dev.gyro_y_adc = (signed short)((data[10] << 8) | data[11]);
icm20608_dev.gyro_z_adc = (signed short)((data[12] << 8) | data[13]);
/* 计算实际值 */
icm20608_dev.gyro_x_act = ((float)(icm20608_dev.gyro_x_adc) / gyroscale) * 100;
icm20608_dev.gyro_y_act = ((float)(icm20608_dev.gyro_y_adc) / gyroscale) * 100;
icm20608_dev.gyro_z_act = ((float)(icm20608_dev.gyro_z_adc) / gyroscale) * 100;
icm20608_dev.accel_x_act = ((float)(icm20608_dev.accel_x_adc) / accescale) * 100;
icm20608_dev.accel_y_act = ((float)(icm20608_dev.accel_y_adc) / accescale) * 100;
icm20608_dev.accel_z_act = ((float)(icm20608_dev.accel_z_adc) / accescale) * 100;
icm20608_dev.temp_act = (((float)(icm20608_dev.temp_adc) - 25 ) / 326.8 + 25) * 100;
}

View File

@@ -0,0 +1,131 @@
#ifndef _BSP_ICM20608_H
#define _BSP_ICM20608_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_icm20608.h
作者 : 左忠凯
版本 : V1.0
描述 : ICM20608驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/3/26 左忠凯创建
***************************************************************/
#include "bsp.h"
#include "bsp_gpio.h"
/* 宏定义 */
#define ICM20608_CSN(n) (n ? gpio_pinwrite(GPIO1, 20, 1) : gpio_pinwrite(GPIO1, 20, 0)) /* SPI片选信号 */
#define ICM20608G_ID 0XAF /* ID值 */
#define ICM20608D_ID 0XAE /* ID值 */
/* ICM20608寄存器
*复位后所有寄存器地址都为0除了
*Register 107(0X6B) Power Management 1 = 0x40
*Register 117(0X75) WHO_AM_I = 0xAF或0xAE
*/
/* 陀螺仪和加速度自测(出产时设置,用于与用户的自检输出值比较) */
#define ICM20_SELF_TEST_X_GYRO 0x00
#define ICM20_SELF_TEST_Y_GYRO 0x01
#define ICM20_SELF_TEST_Z_GYRO 0x02
#define ICM20_SELF_TEST_X_ACCEL 0x0D
#define ICM20_SELF_TEST_Y_ACCEL 0x0E
#define ICM20_SELF_TEST_Z_ACCEL 0x0F
/* 陀螺仪静态偏移 */
#define ICM20_XG_OFFS_USRH 0x13
#define ICM20_XG_OFFS_USRL 0x14
#define ICM20_YG_OFFS_USRH 0x15
#define ICM20_YG_OFFS_USRL 0x16
#define ICM20_ZG_OFFS_USRH 0x17
#define ICM20_ZG_OFFS_USRL 0x18
#define ICM20_SMPLRT_DIV 0x19
#define ICM20_CONFIG 0x1A
#define ICM20_GYRO_CONFIG 0x1B
#define ICM20_ACCEL_CONFIG 0x1C
#define ICM20_ACCEL_CONFIG2 0x1D
#define ICM20_LP_MODE_CFG 0x1E
#define ICM20_ACCEL_WOM_THR 0x1F
#define ICM20_FIFO_EN 0x23
#define ICM20_FSYNC_INT 0x36
#define ICM20_INT_PIN_CFG 0x37
#define ICM20_INT_ENABLE 0x38
#define ICM20_INT_STATUS 0x3A
/* 加速度输出 */
#define ICM20_ACCEL_XOUT_H 0x3B
#define ICM20_ACCEL_XOUT_L 0x3C
#define ICM20_ACCEL_YOUT_H 0x3D
#define ICM20_ACCEL_YOUT_L 0x3E
#define ICM20_ACCEL_ZOUT_H 0x3F
#define ICM20_ACCEL_ZOUT_L 0x40
/* 温度输出 */
#define ICM20_TEMP_OUT_H 0x41
#define ICM20_TEMP_OUT_L 0x42
/* 陀螺仪输出 */
#define ICM20_GYRO_XOUT_H 0x43
#define ICM20_GYRO_XOUT_L 0x44
#define ICM20_GYRO_YOUT_H 0x45
#define ICM20_GYRO_YOUT_L 0x46
#define ICM20_GYRO_ZOUT_H 0x47
#define ICM20_GYRO_ZOUT_L 0x48
#define ICM20_SIGNAL_PATH_RESET 0x68
#define ICM20_ACCEL_INTEL_CTRL 0x69
#define ICM20_USER_CTRL 0x6A
#define ICM20_PWR_MGMT_1 0x6B
#define ICM20_PWR_MGMT_2 0x6C
#define ICM20_FIFO_COUNTH 0x72
#define ICM20_FIFO_COUNTL 0x73
#define ICM20_FIFO_R_W 0x74
#define ICM20_WHO_AM_I 0x75
/* 加速度静态偏移 */
#define ICM20_XA_OFFSET_H 0x77
#define ICM20_XA_OFFSET_L 0x78
#define ICM20_YA_OFFSET_H 0x7A
#define ICM20_YA_OFFSET_L 0x7B
#define ICM20_ZA_OFFSET_H 0x7D
#define ICM20_ZA_OFFSET_L 0x7E
/*
* ICM20608结构体
*/
struct icm20608_dev_struc
{
signed int gyro_x_adc; /* 陀螺仪X轴原始值 */
signed int gyro_y_adc; /* 陀螺仪Y轴原始值 */
signed int gyro_z_adc; /* 陀螺仪Z轴原始值 */
signed int accel_x_adc; /* 加速度计X轴原始值 */
signed int accel_y_adc; /* 加速度计Y轴原始值 */
signed int accel_z_adc; /* 加速度计Z轴原始值 */
signed int temp_adc; /* 温度原始值 */
/* 下面是计算得到的实际值扩大100倍 */
signed int gyro_x_act; /* 陀螺仪X轴实际值 */
signed int gyro_y_act; /* 陀螺仪Y轴实际值 */
signed int gyro_z_act; /* 陀螺仪Z轴实际值 */
signed int accel_x_act; /* 加速度计X轴实际值 */
signed int accel_y_act; /* 加速度计Y轴实际值 */
signed int accel_z_act; /* 加速度计Z轴实际值 */
signed int temp_act; /* 温度实际值 */
};
struct icm20608_dev_struc icm20608_dev; /* icm20608设备 */
/* 函数声明 */
unsigned char icm20608_init(void);
void icm20608_write_reg(unsigned char reg, unsigned char value);
unsigned char icm20608_read_reg(unsigned char reg);
void icm20608_read_len(unsigned char reg, unsigned char *buf, unsigned char len);
void icm20608_getdata(void);
#endif

View File

@@ -0,0 +1,102 @@
#include "bsp_int.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_int.c
作者 : 左忠凯
版本 : V1.0
描述 : 中断驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
/* 中断嵌套计数器 */
static unsigned int irqNesting;
/* 中断服务函数表 */
static sys_irq_handle_t irqTable[NUMBER_OF_INT_VECTORS];
/*
* @description : 中断初始化函数
* @param : 无
* @return : 无
*/
void int_init(void)
{
GIC_Init(); /* 初始化GIC */
system_irqtable_init(); /* 初始化中断表 */
__set_VBAR((uint32_t)0x87800000); /* 中断向量表偏移,偏移到起始地址 */
}
/*
* @description : 初始化中断服务函数表
* @param : 无
* @return : 无
*/
void system_irqtable_init(void)
{
unsigned int i = 0;
irqNesting = 0;
/* 先将所有的中断服务函数设置为默认值 */
for(i = 0; i < NUMBER_OF_INT_VECTORS; i++)
{
system_register_irqhandler((IRQn_Type)i,default_irqhandler, NULL);
}
}
/*
* @description : 给指定的中断号注册中断服务函数
* @param - irq : 要注册的中断号
* @param - handler : 要注册的中断处理函数
* @param - usrParam : 中断服务处理函数参数
* @return : 无
*/
void system_register_irqhandler(IRQn_Type irq, system_irq_handler_t handler, void *userParam)
{
irqTable[irq].irqHandler = handler;
irqTable[irq].userParam = userParam;
}
/*
* @description : C语言中断服务函数irq汇编中断服务函数会
调用此函数,此函数通过在中断服务列表中查
找指定中断号所对应的中断处理函数并执行。
* @param - giccIar : 中断号
* @return : 无
*/
void system_irqhandler(unsigned int giccIar)
{
uint32_t intNum = giccIar & 0x3FFUL;
/* 检查中断号是否符合要求 */
if ((intNum == 1023) || (intNum >= NUMBER_OF_INT_VECTORS))
{
return;
}
irqNesting++; /* 中断嵌套计数器加一 */
/* 根据传递进来的中断号在irqTable中调用确定的中断服务函数*/
irqTable[intNum].irqHandler(intNum, irqTable[intNum].userParam);
irqNesting--; /* 中断执行完成,中断嵌套寄存器减一 */
}
/*
* @description : 默认中断服务函数
* @param - giccIar : 中断号
* @param - usrParam : 中断服务处理函数参数
* @return : 无
*/
void default_irqhandler(unsigned int giccIar, void *userParam)
{
while(1)
{
}
}

View File

@@ -0,0 +1,36 @@
#ifndef _BSP_INT_H
#define _BSP_INT_H
#include "bsp.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_int.c
作者 : 左忠凯
版本 : V1.0
描述 : 中断驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
/* 中断服务函数形式 */
typedef void (*system_irq_handler_t) (unsigned int giccIar, void *param);
/* 中断服务函数结构体*/
typedef struct _sys_irq_handle
{
system_irq_handler_t irqHandler; /* 中断服务函数 */
void *userParam; /* 中断服务函数参数 */
} sys_irq_handle_t;
/* 函数声明 */
void int_init(void);
void system_irqtable_init(void);
void system_register_irqhandler(IRQn_Type irq, system_irq_handler_t handler, void *userParam);
void system_irqhandler(unsigned int giccIar);
void default_irqhandler(unsigned int giccIar, void *userParam);
#endif

View File

@@ -0,0 +1,70 @@
#include "bsp_key.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_key.h
作者 : 左忠凯
版本 : V1.0
描述 : 按键驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
/*
* @description : 初始化按键
* @param : 无
* @return : 无
*/
void key_init(void)
{
gpio_pin_config_t key_config;
/* 1、初始化IO复用, 复用为GPIO1_IO18 */
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);
/* 2、、配置UART1_CTS_B的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 11 默认22K上拉
*bit [13]: 1 pull功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 000 关闭输出
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
/* 3、初始化GPIO */
//GPIO1->GDIR &= ~(1 << 18); /* GPIO1_IO18设置为输入 */
key_config.direction = kGPIO_DigitalInput;
gpio_init(GPIO1,18, &key_config);
}
/*
* @description : 获取按键值
* @param : 无
* @return : 0 没有按键按下,其他值:对应的按键值
*/
int key_getvalue(void)
{
int ret = 0;
static unsigned char release = 1; /* 按键松开 */
if((release==1)&&(gpio_pinread(GPIO1, 18) == 0)) /* KEY0 */
{
delay(10); /* 延时消抖 */
release = 0; /* 标记按键按下 */
if(gpio_pinread(GPIO1, 18) == 0)
ret = KEY0_VALUE;
}
else if(gpio_pinread(GPIO1, 18) == 1)
{
ret = 0;
release = 1; /* 标记按键释放 */
}
return ret;
}

View File

@@ -0,0 +1,29 @@
#ifndef _BSP_KEY_H
#define _BSP_KEY_H
#include "bsp.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_key.h
作者 : 左忠凯
版本 : V1.0
描述 : 按键驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
/* 定义按键值 */
enum keyvalue{
KEY_NONE = 0,
KEY0_VALUE,
KEY1_VALUE,
KEY2_VALUE,
};
/* 函数声明 */
void key_init(void);
int key_getvalue(void);
#endif

View File

@@ -0,0 +1,152 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_keyfilter.c
作者 : 左忠凯
版本 : V1.0
描述 : 定时器按键消抖驱动。
其他 : 按键采用中断方式,按下按键触发按键中断,在按键中断里面
使能定时器定时中断。使用定时器定时中断来完成消抖延时,
定时器中断周期就是延时时间。如果定时器定时中断触发,
表示消抖完成(延时周期完成),即可执行按键处理函数。
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
#include "bsp_key.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_beep.h"
#include "bsp_keyfilter.h"
/*
* @description : 按键初始化
* @param : 无
* @return : 无
*/
void filterkey_init(void)
{
gpio_pin_config_t key_config;
/* 1、初始化IO复用 */
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0); /* 复用为GPIO1_IO18 */
/* 2、、配置GPIO1_IO18的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 11 默认22K上拉
*bit [13]: 1 pull功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 000 关闭输出
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
/* 3、初始化GPIO为中断 */
key_config.direction = kGPIO_DigitalInput;
key_config.interruptMode = kGPIO_IntFallingEdge;
key_config.outputLogic = 1;
gpio_init(GPIO1, 18, &key_config);
GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /* 使能GIC中对应的中断 */
/* 注册中断服务函数 */
system_register_irqhandler(GPIO1_Combined_16_31_IRQn,
(system_irq_handler_t)gpio1_16_31_irqhandler,
NULL);
gpio_enableint(GPIO1, 18); /* 使能GPIO1_IO18的中断功能 */
filtertimer_init(66000000/100); /* 初始化定时器,10ms */
}
/*
* @description : 初始化用于消抖的定时器,默认关闭定时器
* @param - value : 定时器EPIT计数值
* @return : 无
*/
void filtertimer_init(unsigned int value)
{
EPIT1->CR = 0; //先清零
/*
* CR寄存器:
* bit25:24 01 时钟源选择Peripheral clock=66MHz
* bit15:4 0 1分频
* bit3: 1 当计数器到0的话从LR重新加载数值
* bit2: 1 比较中断使能
* bit1: 1 初始计数值来源于LR寄存器值
* bit0: 0 先关闭EPIT1
*/
EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);
/* 计数值 */
EPIT1->LR = value;
/* 比较寄存器,当计数器值和此寄存器值相等的话就会产生中断 */
EPIT1->CMPR = 0;
GIC_EnableIRQ(EPIT1_IRQn); /* 使能GIC中对应的中断 */
/* 注册中断服务函数 */
system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)filtertimer_irqhandler, NULL);
}
/*
* @description : 关闭定时器
* @param : 无
* @return : 无
*/
void filtertimer_stop(void)
{
EPIT1->CR &= ~(1<<0); /* 关闭定时器 */
}
/*
* @description : 重启定时器
* @param - value : 定时器EPIT计数值
* @return : 无
*/
void filtertimer_restart(unsigned int value)
{
EPIT1->CR &= ~(1<<0); /* 先关闭定时器 */
EPIT1->LR = value; /* 计数值 */
EPIT1->CR |= (1<<0); /* 打开定时器 */
}
/*
* @description : 定时器中断处理函数
* @param : 无
* @return : 无
*/
void filtertimer_irqhandler(void)
{
static unsigned char state = OFF;
if(EPIT1->SR & (1<<0)) /* 判断比较事件是否发生 */
{
filtertimer_stop(); /* 关闭定时器 */
if(gpio_pinread(GPIO1, 18) == 0) /* KEY0 */
{
state = !state;
beep_switch(state); /* 反转蜂鸣器 */
}
}
EPIT1->SR |= 1<<0; /* 清除中断标志位 */
}
/*
* @description : GPIO中断处理函数
* @param : 无
* @return : 无
*/
void gpio1_16_31_irqhandler(void)
{
/* 开启定时器 */
filtertimer_restart(66000000/100);
/* 清除中断标志位 */
gpio_clearintflags(GPIO1, 18);
}

View File

@@ -0,0 +1,23 @@
#ifndef _BSP_KEYFILTER_H
#define _BSP_KEYFILTER_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_keyfilter.c
作者 : 左忠凯
版本 : V1.0
描述 : 定时器按键消抖驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
/* 函数声明 */
void filterkey_init(void);
void filtertimer_init(unsigned int value);
void filtertimer_stop(void);
void filtertimer_restart(unsigned int value);
void filtertimer_irqhandler(void);
void gpio1_16_31_irqhandler(void);
#endif

View File

@@ -0,0 +1,413 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_lcd.c
作者 : 左忠凯
版本 : V1.0
描述 : LCD驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
#include "bsp_lcd.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
#include "printf.h"
/* 液晶屏参数结构体 */
struct tftlcd_typedef tftlcd_dev;
/*
* @description : 始化LCD
* @param : 无
* @return : 无
*/
void lcd_init(void)
{
lcdgpio_init(); /* 初始化IO */
lcdclk_init(32, 3, 5); /* 初始化LCD时钟 */
lcd_reset(); /* 复位LCD */
delayms(10); /* 延时10ms */
lcd_noreset(); /* 结束复位 */
/* TFTLCD参数结构体初始化 */
tftlcd_dev.height = 600;
tftlcd_dev.width = 1024;
tftlcd_dev.pixsize = 4; /* ARGB8888模式每个像素4字节 */
tftlcd_dev.vspw = 3;
tftlcd_dev.vbpd = 20;
tftlcd_dev.vfpd = 12;
tftlcd_dev.hspw = 20;
tftlcd_dev.hbpd = 140;
tftlcd_dev.hfpd = 160;
tftlcd_dev.framebuffer = LCD_FRAMEBUF_ADDR;
tftlcd_dev.backcolor = LCD_WHITE; /* 背景色为白色 */
tftlcd_dev.forecolor = LCD_BLACK; /* 前景色为黑色 */
/* 初始化ELCDIF的CTRL寄存器
* bit [31] 0 : 停止复位
* bit [19] 1 : 旁路计数器模式
* bit [17] 1 : LCD工作在dotclk模式
* bit [15:14] 00 : 输入数据不交换
* bit [13:12] 00 : CSC不交换
* bit [11:10] 11 : 24位总线宽度
* bit [9:8] 11 : 24位数据宽度,也就是RGB888
* bit [5] 1 : elcdif工作在主模式
* bit [1] 0 : 所有的24位均有效
*/
LCDIF->CTRL |= (1 << 19) | (1 << 17) | (0 << 14) | (0 << 12) |
(3 << 10) | (3 << 8) | (1 << 5) | (0 << 1);
/*
* 初始化ELCDIF的寄存器CTRL1
* bit [19:16] : 0X7 ARGB模式下传输24位数据A通道不用传输
*/
LCDIF->CTRL1 = 0X7 << 16;
/*
* 初始化ELCDIF的寄存器TRANSFER_COUNT寄存器
* bit [31:16] : 高度
* bit [15:0] : 宽度
*/
LCDIF->TRANSFER_COUNT = (tftlcd_dev.height << 16) | (tftlcd_dev.width << 0);
/*
* 初始化ELCDIF的VDCTRL0寄存器
* bit [29] 0 : VSYNC输出
* bit [28] 1 : 使能ENABLE输出
* bit [27] 0 : VSYNC低电平有效
* bit [26] 0 : HSYNC低电平有效
* bit [25] 0 : DOTCLK上升沿有效
* bit [24] 1 : ENABLE信号高电平有效
* bit [21] 1 : DOTCLK模式下设置为1
* bit [20] 1 : DOTCLK模式下设置为1
* bit [17:0] : vsw参数
*/
LCDIF->VDCTRL0 = 0; //先清零
LCDIF->VDCTRL0 = (0 << 29) | (1 << 28) | (0 << 27) |
(0 << 26) | (0 << 25) | (1 << 24) |
(1 << 21) | (1 << 20) | (tftlcd_dev.vspw << 0);
/*
* 初始化ELCDIF的VDCTRL1寄存器
* 设置VSYNC总周期
*/
LCDIF->VDCTRL1 = tftlcd_dev.height + tftlcd_dev.vspw + tftlcd_dev.vfpd + tftlcd_dev.vbpd; //VSYNC周期
/*
* 初始化ELCDIF的VDCTRL2寄存器
* 设置HSYNC周期
* bit[31:18] hsw
* bit[17:0] : HSYNC总周期
*/
LCDIF->VDCTRL2 = (tftlcd_dev.hspw << 18) | (tftlcd_dev.width + tftlcd_dev.hspw + tftlcd_dev.hfpd + tftlcd_dev.hbpd);
/*
* 初始化ELCDIF的VDCTRL3寄存器
* 设置HSYNC周期
* bit[27:16] :水平等待时钟数
* bit[15:0] : 垂直等待时钟数
*/
LCDIF->VDCTRL3 = ((tftlcd_dev.hbpd + tftlcd_dev.hspw) << 16) | (tftlcd_dev.vbpd + tftlcd_dev.vspw);
/*
* 初始化ELCDIF的VDCTRL4寄存器
* 设置HSYNC周期
* bit[18] 1 : 当使用VSHYNC、HSYNC、DOTCLK的话此为置1
* bit[17:0] : 宽度
*/
LCDIF->VDCTRL4 = (1<<18) | (tftlcd_dev.width);
/*
* 初始化ELCDIF的CUR_BUF和NEXT_BUF寄存器
* 设置当前显存地址和下一帧的显存地址
*/
LCDIF->CUR_BUF = (unsigned int)tftlcd_dev.framebuffer;
LCDIF->NEXT_BUF = (unsigned int)tftlcd_dev.framebuffer;
lcd_enable(); /* 使能LCD */
delayms(10);
lcd_clear(LCD_WHITE); /* 清屏 */
}
/*
* IO引脚: LCD_DATA00 -> LCD_B0
* LCD_DATA01 -> LCD_B1
* LCD_DATA02 -> LCD_B2
* LCD_DATA03 -> LCD_B3
* LCD_DATA04 -> LCD_B4
* LCD_DATA05 -> LCD_B5
* LCD_DATA06 -> LCD_B6
* LCD_DATA07 -> LCD_B7
*
* LCD_DATA08 -> LCD_G0
* LCD_DATA09 -> LCD_G1
* LCD_DATA010 -> LCD_G2
* LCD_DATA011 -> LCD_G3
* LCD_DATA012 -> LCD_G4
* LCD_DATA012 -> LCD_G4
* LCD_DATA013 -> LCD_G5
* LCD_DATA014 -> LCD_G6
* LCD_DATA015 -> LCD_G7
*
* LCD_DATA016 -> LCD_R0
* LCD_DATA017 -> LCD_R1
* LCD_DATA018 -> LCD_R2
* LCD_DATA019 -> LCD_R3
* LCD_DATA020 -> LCD_R4
* LCD_DATA021 -> LCD_R5
* LCD_DATA022 -> LCD_R6
* LCD_DATA023 -> LCD_R7
*
* LCD_CLK -> LCD_CLK
* LCD_VSYNC -> LCD_VSYNC
* LCD_HSYNC -> LCD_HSYNC
* LCD_DE -> LCD_DE
* LCD_BL -> GPIO1_IO08
*/
/*
* @description : LCD GPIO初始化
* @param : 无
* @return : 无
*/
void lcdgpio_init(void)
{
gpio_pin_config_t gpio_config;
/* 1、IO初始化复用功能 */
IOMUXC_SetPinMux(IOMUXC_LCD_DATA00_LCDIF_DATA00,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA01_LCDIF_DATA01,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA02_LCDIF_DATA02,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA03_LCDIF_DATA03,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA04_LCDIF_DATA04,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA05_LCDIF_DATA05,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA06_LCDIF_DATA06,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_LCDIF_DATA07,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA08_LCDIF_DATA08,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA09_LCDIF_DATA09,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA10_LCDIF_DATA10,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA11_LCDIF_DATA11,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA12_LCDIF_DATA12,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA13_LCDIF_DATA13,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA14_LCDIF_DATA14,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_LCDIF_DATA15,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA16_LCDIF_DATA16,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA17_LCDIF_DATA17,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA18_LCDIF_DATA18,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA19_LCDIF_DATA19,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA20_LCDIF_DATA20,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA21_LCDIF_DATA21,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA22_LCDIF_DATA22,0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_LCDIF_DATA23,0);
IOMUXC_SetPinMux(IOMUXC_LCD_CLK_LCDIF_CLK,0);
IOMUXC_SetPinMux(IOMUXC_LCD_ENABLE_LCDIF_ENABLE,0);
IOMUXC_SetPinMux(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0);
IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0);
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_GPIO1_IO08,0); /* 背光BL引脚 */
/* 2、配置LCD IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 0 默认22K上拉
*bit [13]: 0 pull功能
*bit [12]: 0 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 111 驱动能力为R0/7
*bit [0]: 1 高转换率
*/
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA00_LCDIF_DATA00,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA01_LCDIF_DATA01,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA02_LCDIF_DATA02,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA03_LCDIF_DATA03,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA04_LCDIF_DATA04,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA05_LCDIF_DATA05,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA06_LCDIF_DATA06,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_LCDIF_DATA07,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA08_LCDIF_DATA08,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA09_LCDIF_DATA09,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA10_LCDIF_DATA10,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA11_LCDIF_DATA11,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA12_LCDIF_DATA12,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA13_LCDIF_DATA13,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA14_LCDIF_DATA14,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_LCDIF_DATA15,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA16_LCDIF_DATA16,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA17_LCDIF_DATA17,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA18_LCDIF_DATA18,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA19_LCDIF_DATA19,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA20_LCDIF_DATA20,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA21_LCDIF_DATA21,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA22_LCDIF_DATA22,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_LCDIF_DATA23,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_CLK_LCDIF_CLK,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_ENABLE_LCDIF_ENABLE,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0xB9);
IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0xB9);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_GPIO1_IO08,0xB9); /* 背光BL引脚 */
/* GPIO初始化 */
gpio_config.direction = kGPIO_DigitalOutput; /* 输出 */
gpio_config.outputLogic = 1; /* 默认关闭背光 */
gpio_init(GPIO1, 8, &gpio_config); /* 背光默认打开 */
gpio_pinwrite(GPIO1, 8, 1); /* 打开背光 */
}
/*
* @description : LCD时钟初始化, LCD时钟计算公式如下
* LCD CLK = 24 * loopDiv / prediv / div
* @param - loopDiv : loopDivider值
* @param - loopDiv : lcdifprediv值
* @param - div : lcdifdiv值
* @return : 无
*/
void lcdclk_init(unsigned char loopDiv, unsigned char prediv, unsigned char div)
{
/* 先初始化video pll
* VIDEO PLL = OSC24M * (loopDivider + (denominator / numerator)) / postDivider
*不使用小数分频器因此denominator和numerator设置为0
*/
CCM_ANALOG->PLL_VIDEO_NUM = 0; /* 不使用小数分频器 */
CCM_ANALOG->PLL_VIDEO_DENOM = 0;
/*
* PLL_VIDEO寄存器设置
* bit[13]: 1 使能VIDEO PLL时钟
* bit[20:19] 2 设置postDivider为1分频
* bit[6:0] : 32 设置loopDivider寄存器
*/
CCM_ANALOG->PLL_VIDEO = (2 << 19) | (1 << 13) | (loopDiv << 0);
/*
* MISC2寄存器设置
* bit[31:30]: 0 VIDEO的post-div设置时钟源来源于postDivider1分频
*/
CCM_ANALOG->MISC2 &= ~(3 << 30);
CCM_ANALOG->MISC2 = 0 << 30;
/* LCD时钟源来源与PLL5也就是VIDEO PLL */
CCM->CSCDR2 &= ~(7 << 15);
CCM->CSCDR2 |= (2 << 15); /* 设置LCDIF_PRE_CLK使用PLL5 */
/* 设置LCDIF_PRE分频 */
CCM->CSCDR2 &= ~(7 << 12);
CCM->CSCDR2 |= (prediv - 1) << 12; /* 设置分频 */
/* 设置LCDIF分频 */
CCM->CBCMR &= ~(7 << 23);
CCM->CBCMR |= (div - 1) << 23;
/* 设置LCD时钟源为LCDIF_PRE时钟 */
CCM->CSCDR2 &= ~(7 << 9); /* 清除原来的设置 */
CCM->CSCDR2 |= (0 << 9); /* LCDIF_PRE时钟源选择LCDIF_PRE时钟 */
}
/*
* @description : 复位ELCDIF接口
* @param : 无
* @return : 无
*/
void lcd_reset(void)
{
LCDIF->CTRL = 1<<31; /* 强制复位 */
}
/*
* @description : 结束复位ELCDIF接口
* @param : 无
* @return : 无
*/
void lcd_noreset(void)
{
LCDIF->CTRL = 0<<31; /* 取消强制复位 */
}
/*
* @description : 使能ELCDIF接口
* @param : 无
* @return : 无
*/
void lcd_enable(void)
{
LCDIF->CTRL |= 1<<0; /* 使能ELCDIF */
}
/*
* @description : 画点函数
* @param - x : x轴坐标
* @param - y : y轴坐标
* @param - color : 颜色值
* @return : 无
*/
void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color)
{
*(unsigned int*)((unsigned int)tftlcd_dev.framebuffer +
tftlcd_dev.pixsize * (tftlcd_dev.width * y+x))=color;
}
/*
* @description : 读取指定点的颜色值
* @param - x : x轴坐标
* @param - y : y轴坐标
* @return : 读取到的指定点的颜色值
*/
inline unsigned int lcd_readpoint(unsigned short x,unsigned short y)
{
return *(unsigned int*)((unsigned int)tftlcd_dev.framebuffer +
tftlcd_dev.pixsize * (tftlcd_dev.width * y + x));
}
/*
* @description : 清屏
* @param - color : 颜色值
* @return : 读取到的指定点的颜色值
*/
void lcd_clear(unsigned int color)
{
unsigned int num;
unsigned int i = 0;
unsigned int *startaddr=(unsigned int*)tftlcd_dev.framebuffer; //指向帧缓存首地址
num=(unsigned int)tftlcd_dev.width * tftlcd_dev.height; //缓冲区总长度
for(i = 0; i < num; i++)
{
startaddr[i] = color;
}
}
/*
* @description : 以指定的颜色填充一块矩形
* @param - x0 : 矩形起始点坐标X轴
* @param - y0 : 矩形起始点坐标Y轴
* @param - x1 : 矩形终止点坐标X轴
* @param - y1 : 矩形终止点坐标Y轴
* @param - color : 要填充的颜色
* @return : 读取到的指定点的颜色值
*/
void lcd_fill(unsigned short x0, unsigned short y0,
unsigned short x1, unsigned short y1, unsigned int color)
{
unsigned short x, y;
if(x0 < 0) x0 = 0;
if(y0 < 0) y0 = 0;
if(x1 >= tftlcd_dev.width) x1 = tftlcd_dev.width - 1;
if(y1 >= tftlcd_dev.height) y1 = tftlcd_dev.height - 1;
for(y = y0; y <= y1; y++)
{
for(x = x0; x <= x1; x++)
lcd_drawpoint(x, y, color);
}
}

View File

@@ -0,0 +1,79 @@
#ifndef _BSP_LCD_H
#define _BSP_LCD_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_lcd.h
作者 : 左忠凯
版本 : V1.0
描述 : LCD驱动文件头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 颜色 */
#define LCD_BLUE 0x000000FF
#define LCD_GREEN 0x0000FF00
#define LCD_RED 0x00FF0000
#define LCD_CYAN 0x0000FFFF
#define LCD_MAGENTA 0x00FF00FF
#define LCD_YELLOW 0x00FFFF00
#define LCD_LIGHTBLUE 0x008080FF
#define LCD_LIGHTGREEN 0x0080FF80
#define LCD_LIGHTRED 0x00FF8080
#define LCD_LIGHTCYAN 0x0080FFFF
#define LCD_LIGHTMAGENTA 0x00FF80FF
#define LCD_LIGHTYELLOW 0x00FFFF80
#define LCD_DARKBLUE 0x00000080
#define LCD_DARKGREEN 0x00008000
#define LCD_DARKRED 0x00800000
#define LCD_DARKCYAN 0x00008080
#define LCD_DARKMAGENTA 0x00800080
#define LCD_DARKYELLOW 0x00808000
#define LCD_WHITE 0x00FFFFFF
#define LCD_LIGHTGRAY 0x00D3D3D3
#define LCD_GRAY 0x00808080
#define LCD_DARKGRAY 0x00404040
#define LCD_BLACK 0x00000000
#define LCD_BROWN 0x00A52A2A
#define LCD_ORANGE 0x00FFA500
#define LCD_TRANSPARENT 0x00000000
/* LCD显存地址 */
#define LCD_FRAMEBUF_ADDR (0x89000000)
/* LCD控制参数结构体 */
struct tftlcd_typedef{
unsigned short height; /* LCD屏幕高度 */
unsigned short width; /* LCD屏幕宽度 */
unsigned char pixsize; /* LCD每个像素所占字节大小 */
unsigned short vspw;
unsigned short vbpd;
unsigned short vfpd;
unsigned short hspw;
unsigned short hbpd;
unsigned short hfpd;
unsigned int framebuffer; /* LCD显存首地址 */
unsigned int forecolor; /* 前景色 */
unsigned int backcolor; /* 背景色 */
};
extern struct tftlcd_typedef tftlcd_dev;
/* 函数声明 */
void lcd_init(void);
void lcdgpio_init(void);
void lcdclk_init(unsigned char loopDiv, unsigned char prediv, unsigned char div);
void lcd_reset(void);
void lcd_noreset(void);
void lcd_enable(void);
void video_pllinit(unsigned char loopdivi, unsigned char postdivi);
void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color);
inline unsigned int lcd_readpoint(unsigned short x,unsigned short y);
void lcd_clear(unsigned int color);
void lcd_fill(unsigned short x0, unsigned short y0, unsigned short x1, unsigned short y1, unsigned int color);
#endif

View File

@@ -0,0 +1,274 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_lcdapi.c
作者 : 左忠凯
版本 : V1.0
描述 : LCD API函数文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/3/18 左忠凯创建
***************************************************************/
#include "bsp_lcdapi.h"
#include "font.h"
/*
* @description : 画线函数
* @param - x1 : 线起始点坐标X轴
* @param - y1 : 线起始点坐标Y轴
* @param - x2 : 线终止点坐标X轴
* @param - y2 : 线终止点坐标Y轴
* @return : 无
*/
void lcd_drawline(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)
{
u16 t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, uRow, uCol;
delta_x = x2 - x1; /* 计算坐标增量 */
delta_y = y2 - y1;
uRow = x1;
uCol = y1;
if(delta_x > 0) /* 设置单步方向 */
incx = 1;
else if(delta_x==0) /* 垂直线 */
incx = 0;
else
{
incx = -1;
delta_x = -delta_x;
}
if(delta_y>0)
incy=1;
else if(delta_y == 0) /* 水平线 */
incy=0;
else
{
incy = -1;
delta_y = -delta_y;
}
if( delta_x > delta_y) /*选取基本增量坐标轴 */
distance = delta_x;
else
distance = delta_y;
for(t = 0; t <= distance+1; t++ ) /* 画线输出 */
{
lcd_drawpoint(uRow, uCol, tftlcd_dev.forecolor);/* 画点 */
xerr += delta_x ;
yerr += delta_y ;
if(xerr > distance)
{
xerr -= distance;
uRow += incx;
}
if(yerr > distance)
{
yerr -= distance;
uCol += incy;
}
}
}
/*
* @description : 画矩形函数
* @param - x1 : 矩形坐上角坐标X轴
* @param - y1 : 矩形坐上角坐标Y轴
* @param - x2 : 矩形右下角坐标X轴
* @param - y2 : 矩形右下角坐标Y轴
* @return : 无
*/
void lcd_draw_rectangle(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)
{
lcd_drawline(x1, y1, x2, y1);
lcd_drawline(x1, y1, x1, y2);
lcd_drawline(x1, y2, x2, y2);
lcd_drawline(x2, y1, x2, y2);
}
/*
* @description : 在指定位置画一个指定大小的圆
* @param - x0 : 圆心坐标X轴
* @param - y0 : 圆心坐标Y轴
* @param - y2 : 圆形半径
* @return : 无
*/
void lcd_draw_Circle(unsigned short x0,unsigned short y0,unsigned char r)
{
int mx = x0, my = y0;
int x = 0, y = r;
int d = 1 - r;
while(y > x) /* y>x即第一象限的第1区八分圆 */
{
lcd_drawpoint(x + mx, y + my, tftlcd_dev.forecolor);
lcd_drawpoint(y + mx, x + my, tftlcd_dev.forecolor);
lcd_drawpoint(-x + mx, y + my, tftlcd_dev.forecolor);
lcd_drawpoint(-y + mx, x + my, tftlcd_dev.forecolor);
lcd_drawpoint(-x + mx, -y + my, tftlcd_dev.forecolor);
lcd_drawpoint(-y + mx, -x + my, tftlcd_dev.forecolor);
lcd_drawpoint(x + mx, -y + my, tftlcd_dev.forecolor);
lcd_drawpoint(y + mx, -x + my, tftlcd_dev.forecolor);
if( d < 0)
{
d = d + 2 * x + 3;
}
else
{
d= d + 2 * (x - y) + 5;
y--;
}
x++;
}
}
/*
* @description : 在指定位置显示一个字符
* @param - x : 起始坐标X轴
* @param - y : 起始坐标Y轴
* @param - num : 显示字符
* @param - size: 字体大小, 可选12/16/24/32
* @param - mode: 叠加方式(1)还是非叠加方式(0)
* @return : 无
*/
void lcd_showchar(unsigned short x, unsigned short y,
unsigned char num, unsigned char size,
unsigned char mode)
{
unsigned char temp, t1, t;
unsigned short y0 = y;
unsigned char csize = (size / 8+ ((size % 8) ? 1 : 0)) * (size / 2); /* 得到字体一个字符对应点阵集所占的字节数 */
num = num - ' '; /*得到偏移后的值ASCII字库是从空格开始取模所以-' '就是对应字符的字库) */
for(t = 0; t < csize; t++)
{
if(size == 12) temp = asc2_1206[num][t]; /* 调用1206字体 */
else if(size == 16)temp = asc2_1608[num][t]; /* 调用1608字体 */
else if(size == 24)temp = asc2_2412[num][t]; /* 调用2412字体 */
else if(size == 32)temp = asc2_3216[num][t]; /* 调用3216字体 */
else return; /* 没有的字库 */
for(t1 = 0; t1 < 8; t1++)
{
if(temp & 0x80)lcd_drawpoint(x, y, tftlcd_dev.forecolor);
else if(mode==0)lcd_drawpoint(x, y, tftlcd_dev.backcolor);
temp <<= 1;
y++;
if(y >= tftlcd_dev.height) return; /* 超区域了 */
if((y - y0) == size)
{
y = y0;
x++;
if(x >= tftlcd_dev.width) return; /* 超区域了 */
break;
}
}
}
}
/*
* @description : 计算m的n次方
* @param - m : 要计算的值
* @param - n : n次方
* @return : m^n次方.
*/
unsigned int lcd_pow(unsigned char m,unsigned char n)
{
unsigned int result = 1;
while(n--) result *= m;
return result;
}
/*
* @description : 显示指定的数字高位为0的话不显示
* @param - x : 起始坐标点X轴。
* @param - y : 起始坐标点Y轴。
* @param - num : 数值(0~999999999)。
* @param - len : 数字位数。
* @param - size: 字体大小
* @return : 无
*/
void lcd_shownum(unsigned short x,
unsigned short y,
unsigned int num,
unsigned char len,
unsigned char size)
{
unsigned char t, temp;
unsigned char enshow = 0;
for(t = 0; t < len; t++)
{
temp = (num / lcd_pow(10, len - t - 1)) % 10;
if(enshow == 0 && t < (len - 1))
{
if(temp == 0)
{
lcd_showchar(x + (size / 2) * t, y, ' ', size, 0);
continue;
}else enshow = 1;
}
lcd_showchar(x + (size / 2) * t, y, temp + '0', size, 0);
}
}
/*
* @description : 显示指定的数字高位为0,还是显示
* @param - x : 起始坐标点X轴。
* @param - y : 起始坐标点Y轴。
* @param - num : 数值(0~999999999)。
* @param - len : 数字位数。
* @param - size : 字体大小
* @param - mode : [7]:0,不填充;1,填充0.
* [6:1]:保留
* [0]:0,非叠加显示;1,叠加显示.
* @return : 无
*/
void lcd_showxnum(unsigned short x, unsigned short y,
unsigned int num, unsigned char len,
unsigned char size, unsigned char mode)
{
unsigned char t, temp;
unsigned char enshow = 0;
for(t = 0; t < len; t++)
{
temp = (num / lcd_pow(10, len - t- 1)) % 10;
if(enshow == 0 && t < (len - 1))
{
if(temp == 0)
{
if(mode & 0X80) lcd_showchar(x + (size / 2) * t, y, '0', size, mode & 0X01);
else lcd_showchar(x + (size / 2) * t, y , ' ', size, mode & 0X01);
continue;
}else enshow=1;
}
lcd_showchar( x + (size / 2) * t, y, temp + '0' , size , mode & 0X01);
}
}
/*
* @description : 显示一串字符串
* @param - x : 起始坐标点X轴。
* @param - y : 起始坐标点Y轴。
* @param - width : 字符串显示区域长度
* @param - height : 字符串显示区域高度
* @param - size : 字体大小
* @param - p : 要显示的字符串首地址
* @return : 无
*/
void lcd_show_string(unsigned short x,unsigned short y,
unsigned short width,unsigned short height,
unsigned char size,char *p)
{
unsigned char x0 = x;
width += x;
height += y;
while((*p <= '~') &&(*p >= ' ')) /* 判断是不是非法字符! */
{
if(x >= width) {x = x0; y += size;}
if(y >= height) break; /* 退出 */
lcd_showchar(x, y, *p , size, 0);
x += size / 2;
p++;
}
}

View File

@@ -0,0 +1,28 @@
#ifndef BSP_LCDAPI_H
#define BSP_LCDAPI_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_lcdapi.h
作者 : 左忠凯
版本 : V1.0
描述 : LCD显示API函数。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/3/18 左忠凯创建
***************************************************************/
#include "bsp.h"
#include "bsp_lcd.h"
/* 函数声明 */
void lcd_drawline(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2);
void lcd_draw_rectangle(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2);
void lcd_draw_Circle(unsigned short x0,unsigned short y0,unsigned char r);
void lcd_showchar(unsigned short x,unsigned short y,unsigned char num,unsigned char size, unsigned char mode);
unsigned int lcd_pow(unsigned char m,unsigned char n);
void lcd_shownum(unsigned short x, unsigned short y, unsigned int num, unsigned char len,unsigned char size);
void lcd_showxnum(unsigned short x, unsigned short y, unsigned int num, unsigned char len, unsigned char size, unsigned char mode);
void lcd_show_string(unsigned short x,unsigned short y,
unsigned short width, unsigned short height, unsigned char size,char *p);
#endif

View File

@@ -0,0 +1,406 @@
#ifndef __FONT_H
#define __FONT_H
//常用ASCII表
//偏移量32
//ASCII字符集: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
//PC2LCD2002取模方式设置阴码+逐列式+顺向+C51格式
//总共3个字符集12*12、16*16、24*24和32*32用户可以自行新增其他分辨率的字符集。
//每个字符所占用的字节数为:(size/8+((size%8)?1:0))*(size/2),其中size:是字库生成时的点阵大小(12/16/24/32...)
//12*12 ASCII字符集点阵
const unsigned char asc2_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x40,0x00,0x00,0x00},/*""",2*/
{0x09,0x00,0x0B,0xC0,0x3D,0x00,0x0B,0xC0,0x3D,0x00,0x09,0x00},/*"#",3*/
{0x18,0xC0,0x24,0x40,0x7F,0xE0,0x22,0x40,0x31,0x80,0x00,0x00},/*"$",4*/
{0x18,0x00,0x24,0xC0,0x1B,0x00,0x0D,0x80,0x32,0x40,0x01,0x80},/*"%",5*/
{0x03,0x80,0x1C,0x40,0x27,0x40,0x1C,0x80,0x07,0x40,0x00,0x40},/*"&",6*/
{0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x40,0x20},/*"(",8*/
{0x00,0x00,0x40,0x20,0x20,0x40,0x1F,0x80,0x00,0x00,0x00,0x00},/*")",9*/
{0x09,0x00,0x06,0x00,0x1F,0x80,0x06,0x00,0x09,0x00,0x00,0x00},/*"*",10*/
{0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x00,0x00},/*"+",11*/
{0x00,0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x20,0x01,0xC0,0x06,0x00,0x38,0x00,0x40,0x00,0x00,0x00},/*"/",15*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"0",16*/
{0x00,0x00,0x10,0x40,0x3F,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"1",17*/
{0x18,0xC0,0x21,0x40,0x22,0x40,0x24,0x40,0x18,0x40,0x00,0x00},/*"2",18*/
{0x10,0x80,0x20,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"3",19*/
{0x02,0x00,0x0D,0x00,0x11,0x00,0x3F,0xC0,0x01,0x40,0x00,0x00},/*"4",20*/
{0x3C,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x23,0x80,0x00,0x00},/*"5",21*/
{0x1F,0x80,0x24,0x40,0x24,0x40,0x34,0x40,0x03,0x80,0x00,0x00},/*"6",22*/
{0x30,0x00,0x20,0x00,0x27,0xC0,0x38,0x00,0x20,0x00,0x00,0x00},/*"7",23*/
{0x1B,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"8",24*/
{0x1C,0x00,0x22,0xC0,0x22,0x40,0x22,0x40,0x1F,0x80,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x08,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40},/*"<",28*/
{0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x40,0x40,0x20,0x80,0x11,0x00,0x0A,0x00,0x04,0x00},/*">",30*/
{0x18,0x00,0x20,0x00,0x23,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"?",31*/
{0x1F,0x80,0x20,0x40,0x27,0x40,0x29,0x40,0x1F,0x40,0x00,0x00},/*"@",32*/
{0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40},/*"A",33*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"B",34*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x30,0x80,0x00,0x00},/*"C",35*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"D",36*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x40,0x30,0xC0,0x00,0x00},/*"E",37*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x00,0x30,0x00,0x00,0x00},/*"F",38*/
{0x0F,0x00,0x10,0x80,0x20,0x40,0x22,0x40,0x33,0x80,0x02,0x00},/*"G",39*/
{0x20,0x40,0x3F,0xC0,0x04,0x00,0x04,0x00,0x3F,0xC0,0x20,0x40},/*"H",40*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x00,0x00},/*"I",41*/
{0x00,0x60,0x20,0x20,0x20,0x20,0x3F,0xC0,0x20,0x00,0x20,0x00},/*"J",42*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x0B,0x00,0x30,0xC0,0x20,0x40},/*"K",43*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x00,0x40,0x00,0x40,0x00,0xC0},/*"L",44*/
{0x3F,0xC0,0x3C,0x00,0x03,0xC0,0x3C,0x00,0x3F,0xC0,0x00,0x00},/*"M",45*/
{0x20,0x40,0x3F,0xC0,0x0C,0x40,0x23,0x00,0x3F,0xC0,0x20,0x00},/*"N",46*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"O",47*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"P",48*/
{0x1F,0x80,0x21,0x40,0x21,0x40,0x20,0xE0,0x1F,0xA0,0x00,0x00},/*"Q",49*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x26,0x00,0x19,0xC0,0x00,0x40},/*"R",50*/
{0x18,0xC0,0x24,0x40,0x24,0x40,0x22,0x40,0x31,0x80,0x00,0x00},/*"S",51*/
{0x30,0x00,0x20,0x40,0x3F,0xC0,0x20,0x40,0x30,0x00,0x00,0x00},/*"T",52*/
{0x20,0x00,0x3F,0x80,0x00,0x40,0x00,0x40,0x3F,0x80,0x20,0x00},/*"U",53*/
{0x20,0x00,0x3E,0x00,0x01,0xC0,0x07,0x00,0x38,0x00,0x20,0x00},/*"V",54*/
{0x38,0x00,0x07,0xC0,0x3C,0x00,0x07,0xC0,0x38,0x00,0x00,0x00},/*"W",55*/
{0x20,0x40,0x39,0xC0,0x06,0x00,0x39,0xC0,0x20,0x40,0x00,0x00},/*"X",56*/
{0x20,0x00,0x38,0x40,0x07,0xC0,0x38,0x40,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x30,0x40,0x21,0xC0,0x26,0x40,0x38,0x40,0x20,0xC0,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x7F,0xE0,0x40,0x20,0x40,0x20,0x00,0x00},/*"[",59*/
{0x00,0x00,0x70,0x00,0x0C,0x00,0x03,0x80,0x00,0x40,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x20,0x40,0x20,0x7F,0xE0,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10},/*"_",63*/
{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x02,0x80,0x05,0x40,0x05,0x40,0x03,0xC0,0x00,0x40},/*"a",65*/
{0x20,0x00,0x3F,0xC0,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"b",66*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x06,0x40,0x00,0x00},/*"c",67*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x24,0x40,0x3F,0xC0,0x00,0x40},/*"d",68*/
{0x00,0x00,0x03,0x80,0x05,0x40,0x05,0x40,0x03,0x40,0x00,0x00},/*"e",69*/
{0x00,0x00,0x04,0x40,0x1F,0xC0,0x24,0x40,0x24,0x40,0x20,0x00},/*"f",70*/
{0x00,0x00,0x02,0xE0,0x05,0x50,0x05,0x50,0x06,0x50,0x04,0x20},/*"g",71*/
{0x20,0x40,0x3F,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"h",72*/
{0x00,0x00,0x04,0x40,0x27,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x10,0x00,0x10,0x04,0x10,0x27,0xE0,0x00,0x00,0x00,0x00},/*"j",74*/
{0x20,0x40,0x3F,0xC0,0x01,0x40,0x07,0x00,0x04,0xC0,0x04,0x40},/*"k",75*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x00,0x40,0x00,0x40,0x00,0x00},/*"l",76*/
{0x07,0xC0,0x04,0x00,0x07,0xC0,0x04,0x00,0x03,0xC0,0x00,0x00},/*"m",77*/
{0x04,0x40,0x07,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"n",78*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"o",79*/
{0x04,0x10,0x07,0xF0,0x04,0x50,0x04,0x40,0x03,0x80,0x00,0x00},/*"p",80*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x50,0x07,0xF0,0x00,0x10},/*"q",81*/
{0x04,0x40,0x07,0xC0,0x02,0x40,0x04,0x00,0x04,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x06,0x40,0x05,0x40,0x05,0x40,0x04,0xC0,0x00,0x00},/*"s",83*/
{0x00,0x00,0x04,0x00,0x1F,0x80,0x04,0x40,0x00,0x40,0x00,0x00},/*"t",84*/
{0x04,0x00,0x07,0x80,0x00,0x40,0x04,0x40,0x07,0xC0,0x00,0x40},/*"u",85*/
{0x04,0x00,0x07,0x00,0x04,0xC0,0x01,0x80,0x06,0x00,0x04,0x00},/*"v",86*/
{0x06,0x00,0x01,0xC0,0x07,0x00,0x01,0xC0,0x06,0x00,0x00,0x00},/*"w",87*/
{0x04,0x40,0x06,0xC0,0x01,0x00,0x06,0xC0,0x04,0x40,0x00,0x00},/*"x",88*/
{0x04,0x10,0x07,0x10,0x04,0xE0,0x01,0x80,0x06,0x00,0x04,0x00},/*"y",89*/
{0x00,0x00,0x04,0x40,0x05,0xC0,0x06,0x40,0x04,0x40,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x7B,0xE0,0x40,0x20,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x20,0x7B,0xE0,0x04,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
};
//16*16 ASCII字符集点阵
const unsigned char asc2_1608[95][16]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xCC,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x00,0x00},/*""",2*/
{0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x00,0x00},/*"#",3*/
{0x00,0x00,0x0E,0x18,0x11,0x04,0x3F,0xFF,0x10,0x84,0x0C,0x78,0x00,0x00,0x00,0x00},/*"$",4*/
{0x0F,0x00,0x10,0x84,0x0F,0x38,0x00,0xC0,0x07,0x78,0x18,0x84,0x00,0x78,0x00,0x00},/*"%",5*/
{0x00,0x78,0x0F,0x84,0x10,0xC4,0x11,0x24,0x0E,0x98,0x00,0xE4,0x00,0x84,0x00,0x08},/*"&",6*/
{0x08,0x00,0x68,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x18,0x18,0x20,0x04,0x40,0x02,0x00,0x00},/*"(",8*/
{0x00,0x00,0x40,0x02,0x20,0x04,0x18,0x18,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x02,0x40,0x02,0x40,0x01,0x80,0x0F,0xF0,0x01,0x80,0x02,0x40,0x02,0x40,0x00,0x00},/*"*",10*/
{0x00,0x80,0x00,0x80,0x00,0x80,0x0F,0xF8,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00},/*"+",11*/
{0x00,0x01,0x00,0x0D,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80},/*"-",13*/
{0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00},/*"/",15*/
{0x00,0x00,0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"0",16*/
{0x00,0x00,0x08,0x04,0x08,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x0E,0x0C,0x10,0x14,0x10,0x24,0x10,0x44,0x11,0x84,0x0E,0x0C,0x00,0x00},/*"2",18*/
{0x00,0x00,0x0C,0x18,0x10,0x04,0x11,0x04,0x11,0x04,0x12,0x88,0x0C,0x70,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0xE0,0x03,0x20,0x04,0x24,0x08,0x24,0x1F,0xFC,0x00,0x24,0x00,0x00},/*"4",20*/
{0x00,0x00,0x1F,0x98,0x10,0x84,0x11,0x04,0x11,0x04,0x10,0x88,0x10,0x70,0x00,0x00},/*"5",21*/
{0x00,0x00,0x07,0xF0,0x08,0x88,0x11,0x04,0x11,0x04,0x18,0x88,0x00,0x70,0x00,0x00},/*"6",22*/
{0x00,0x00,0x1C,0x00,0x10,0x00,0x10,0xFC,0x13,0x00,0x1C,0x00,0x10,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x0E,0x38,0x11,0x44,0x10,0x84,0x10,0x84,0x11,0x44,0x0E,0x38,0x00,0x00},/*"8",24*/
{0x00,0x00,0x07,0x00,0x08,0x8C,0x10,0x44,0x10,0x44,0x08,0x88,0x07,0xF0,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x03,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10,0x04,0x00,0x00},/*"<",28*/
{0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x00,0x00},/*"=",29*/
{0x00,0x00,0x10,0x04,0x08,0x08,0x04,0x10,0x02,0x20,0x01,0x40,0x00,0x80,0x00,0x00},/*">",30*/
{0x00,0x00,0x0E,0x00,0x12,0x00,0x10,0x0C,0x10,0x6C,0x10,0x80,0x0F,0x00,0x00,0x00},/*"?",31*/
{0x03,0xE0,0x0C,0x18,0x13,0xE4,0x14,0x24,0x17,0xC4,0x08,0x28,0x07,0xD0,0x00,0x00},/*"@",32*/
{0x00,0x04,0x00,0x3C,0x03,0xC4,0x1C,0x40,0x07,0x40,0x00,0xE4,0x00,0x1C,0x00,0x04},/*"A",33*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x11,0x04,0x0E,0x88,0x00,0x70,0x00,0x00},/*"B",34*/
{0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x08,0x1C,0x10,0x00,0x00},/*"C",35*/
{0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"D",36*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x17,0xC4,0x10,0x04,0x08,0x18,0x00,0x00},/*"E",37*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x17,0xC0,0x10,0x00,0x08,0x00,0x00,0x00},/*"F",38*/
{0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x44,0x1C,0x78,0x00,0x40,0x00,0x00},/*"G",39*/
{0x10,0x04,0x1F,0xFC,0x10,0x84,0x00,0x80,0x00,0x80,0x10,0x84,0x1F,0xFC,0x10,0x04},/*"H",40*/
{0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x03,0x00,0x01,0x10,0x01,0x10,0x01,0x1F,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"J",42*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x03,0x80,0x14,0x64,0x18,0x1C,0x10,0x04,0x00,0x00},/*"K",43*/
{0x10,0x04,0x1F,0xFC,0x10,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00,0x00},/*"L",44*/
{0x10,0x04,0x1F,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x1F,0xFC,0x10,0x04,0x00,0x00},/*"M",45*/
{0x10,0x04,0x1F,0xFC,0x0C,0x04,0x03,0x00,0x00,0xE0,0x10,0x18,0x1F,0xFC,0x10,0x00},/*"N",46*/
{0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"O",47*/
{0x10,0x04,0x1F,0xFC,0x10,0x84,0x10,0x80,0x10,0x80,0x10,0x80,0x0F,0x00,0x00,0x00},/*"P",48*/
{0x07,0xF0,0x08,0x18,0x10,0x24,0x10,0x24,0x10,0x1C,0x08,0x0A,0x07,0xF2,0x00,0x00},/*"Q",49*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x11,0xC0,0x11,0x30,0x0E,0x0C,0x00,0x04},/*"R",50*/
{0x00,0x00,0x0E,0x1C,0x11,0x04,0x10,0x84,0x10,0x84,0x10,0x44,0x1C,0x38,0x00,0x00},/*"S",51*/
{0x18,0x00,0x10,0x00,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x00,0x18,0x00,0x00,0x00},/*"T",52*/
{0x10,0x00,0x1F,0xF8,0x10,0x04,0x00,0x04,0x00,0x04,0x10,0x04,0x1F,0xF8,0x10,0x00},/*"U",53*/
{0x10,0x00,0x1E,0x00,0x11,0xE0,0x00,0x1C,0x00,0x70,0x13,0x80,0x1C,0x00,0x10,0x00},/*"V",54*/
{0x1F,0xC0,0x10,0x3C,0x00,0xE0,0x1F,0x00,0x00,0xE0,0x10,0x3C,0x1F,0xC0,0x00,0x00},/*"W",55*/
{0x10,0x04,0x18,0x0C,0x16,0x34,0x01,0xC0,0x01,0xC0,0x16,0x34,0x18,0x0C,0x10,0x04},/*"X",56*/
{0x10,0x00,0x1C,0x00,0x13,0x04,0x00,0xFC,0x13,0x04,0x1C,0x00,0x10,0x00,0x00,0x00},/*"Y",57*/
{0x08,0x04,0x10,0x1C,0x10,0x64,0x10,0x84,0x13,0x04,0x1C,0x04,0x10,0x18,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00},/*"[",59*/
{0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x80,0x00,0x60,0x00,0x1C,0x00,0x03,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00},/*"^",62*/
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01},/*"_",63*/
{0x00,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x98,0x01,0x24,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xFC,0x00,0x04},/*"a",65*/
{0x10,0x00,0x1F,0xFC,0x00,0x88,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x11,0x08,0x1F,0xFC,0x00,0x04},/*"d",68*/
{0x00,0x00,0x00,0xF8,0x01,0x44,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xC8,0x00,0x00},/*"e",69*/
{0x00,0x00,0x01,0x04,0x01,0x04,0x0F,0xFC,0x11,0x04,0x11,0x04,0x11,0x00,0x18,0x00},/*"f",70*/
{0x00,0x00,0x00,0xD6,0x01,0x29,0x01,0x29,0x01,0x29,0x01,0xC9,0x01,0x06,0x00,0x00},/*"g",71*/
{0x10,0x04,0x1F,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"h",72*/
{0x00,0x00,0x01,0x04,0x19,0x04,0x19,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x03,0x00,0x01,0x01,0x01,0x19,0x01,0x19,0xFE,0x00,0x00,0x00,0x00},/*"j",74*/
{0x10,0x04,0x1F,0xFC,0x00,0x24,0x00,0x40,0x01,0xB4,0x01,0x0C,0x01,0x04,0x00,0x00},/*"k",75*/
{0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"l",76*/
{0x01,0x04,0x01,0xFC,0x01,0x04,0x01,0x00,0x01,0xFC,0x01,0x04,0x01,0x00,0x00,0xFC},/*"m",77*/
{0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"n",78*/
{0x00,0x00,0x00,0xF8,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0xF8,0x00,0x00},/*"o",79*/
{0x01,0x01,0x01,0xFF,0x00,0x85,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x05,0x01,0xFF,0x00,0x01},/*"q",81*/
{0x01,0x04,0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x04,0x01,0x00,0x01,0x80,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0xCC,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x98,0x00,0x00},/*"s",83*/
{0x00,0x00,0x01,0x00,0x01,0x00,0x07,0xF8,0x01,0x04,0x01,0x04,0x00,0x00,0x00,0x00},/*"t",84*/
{0x01,0x00,0x01,0xF8,0x00,0x04,0x00,0x04,0x00,0x04,0x01,0x08,0x01,0xFC,0x00,0x04},/*"u",85*/
{0x01,0x00,0x01,0x80,0x01,0x70,0x00,0x0C,0x00,0x10,0x01,0x60,0x01,0x80,0x01,0x00},/*"v",86*/
{0x01,0xF0,0x01,0x0C,0x00,0x30,0x01,0xC0,0x00,0x30,0x01,0x0C,0x01,0xF0,0x01,0x00},/*"w",87*/
{0x00,0x00,0x01,0x04,0x01,0x8C,0x00,0x74,0x01,0x70,0x01,0x8C,0x01,0x04,0x00,0x00},/*"x",88*/
{0x01,0x01,0x01,0x81,0x01,0x71,0x00,0x0E,0x00,0x18,0x01,0x60,0x01,0x80,0x01,0x00},/*"y",89*/
{0x00,0x00,0x01,0x84,0x01,0x0C,0x01,0x34,0x01,0x44,0x01,0x84,0x01,0x0C,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x3E,0xFC,0x40,0x02,0x40,0x02},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x3E,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x60,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*"~",94*/
};
//24*24 ASICII字符集点阵
const unsigned char asc2_2412[95][36]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0x0F,0xFE,0x38,0x0F,0x80,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0x00,0x38,0x00,0x00,0x31,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0x00,0x38,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x00,0x61,0x80,0x00,0x67,0xF8,0x07,0xF9,0x80,0x00,0x61,0x80,0x00,0x61,0x80,0x00,0x61,0x80,0x00,0x61,0x80,0x00,0x67,0xF8,0x07,0xF9,0x80,0x00,0x61,0x80,0x00,0x00,0x00},/*"#",3*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0xE0,0x03,0xE0,0xF0,0x06,0x30,0x08,0x04,0x18,0x08,0x1F,0xFF,0xFE,0x04,0x0E,0x08,0x07,0x87,0xF0,0x03,0x81,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*"$",4*/
{0x01,0xF0,0x00,0x06,0x0C,0x00,0x04,0x04,0x08,0x06,0x0C,0x70,0x01,0xF9,0xC0,0x00,0x0E,0x00,0x00,0x3B,0xE0,0x00,0xEC,0x18,0x07,0x08,0x08,0x04,0x0C,0x18,0x00,0x03,0xE0,0x00,0x00,0x00},/*"%",5*/
{0x00,0x01,0xE0,0x00,0x07,0xF0,0x03,0xF8,0x18,0x04,0x1C,0x08,0x04,0x17,0x08,0x07,0xE1,0xD0,0x03,0xC0,0xE0,0x00,0x23,0xB0,0x00,0x3C,0x08,0x00,0x20,0x08,0x00,0x00,0x10,0x00,0x00,0x00},/*"&",6*/
{0x00,0x00,0x00,0x01,0x00,0x00,0x31,0x00,0x00,0x32,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0xFF,0xC0,0x07,0x80,0xF0,0x0C,0x00,0x18,0x10,0x00,0x04,0x20,0x00,0x02,0x00,0x00,0x00},/*"(",8*/
{0x00,0x00,0x00,0x20,0x00,0x02,0x10,0x00,0x04,0x0C,0x00,0x18,0x07,0x80,0xF0,0x01,0xFF,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x00,0x00,0x00,0x00,0x42,0x00,0x00,0x66,0x00,0x00,0x66,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,0x03,0xFF,0xC0,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x66,0x00,0x00,0x66,0x00,0x00,0x42,0x00},/*"*",10*/
{0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x01,0xFF,0xC0,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00},/*"+",11*/
{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x31,0x00,0x00,0x32,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x1C,0x00,0x00,0x70,0x00,0x01,0x80,0x00,0x0E,0x00,0x00,0x38,0x00,0x00,0xC0,0x00,0x07,0x00,0x00,0x1C,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00},/*"/",15*/
{0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x06,0x00,0x18,0x03,0x80,0x70,0x01,0xFF,0xE0,0x00,0x7F,0x80,0x00,0x00,0x00},/*"0",16*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x03,0xFF,0xF8,0x07,0xFF,0xF8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x00,0x01,0xC0,0x38,0x02,0xC0,0x58,0x04,0x00,0x98,0x04,0x01,0x18,0x04,0x02,0x18,0x04,0x04,0x18,0x06,0x1C,0x18,0x03,0xF8,0x18,0x01,0xE0,0xF8,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",18*/
{0x00,0x00,0x00,0x01,0xC0,0xE0,0x03,0xC0,0xF0,0x04,0x00,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x06,0x18,0x08,0x03,0xF4,0x18,0x01,0xE7,0xF0,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x0D,0x00,0x00,0x11,0x00,0x00,0x61,0x00,0x00,0x81,0x08,0x03,0x01,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x01,0x08,0x00,0x01,0x08,0x00,0x00,0x00},/*"4",20*/
{0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0xFC,0xD0,0x06,0x08,0x08,0x06,0x10,0x08,0x06,0x10,0x08,0x06,0x10,0x08,0x06,0x18,0x38,0x06,0x0F,0xF0,0x06,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",21*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xE0,0x03,0x84,0x30,0x02,0x08,0x18,0x04,0x10,0x08,0x04,0x10,0x08,0x04,0x10,0x08,0x07,0x18,0x10,0x03,0x0F,0xF0,0x00,0x07,0xC0,0x00,0x00,0x00},/*"6",22*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0xF8,0x06,0x07,0xF8,0x06,0x18,0x00,0x06,0xE0,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x00,0x01,0xE1,0xE0,0x03,0xF7,0xF0,0x06,0x34,0x10,0x04,0x18,0x08,0x04,0x18,0x08,0x04,0x0C,0x08,0x04,0x0C,0x08,0x06,0x16,0x18,0x03,0xF3,0xF0,0x01,0xC1,0xE0,0x00,0x00,0x00},/*"8",24*/
{0x00,0x00,0x00,0x00,0xF8,0x00,0x03,0xFC,0x30,0x03,0x06,0x38,0x04,0x02,0x08,0x04,0x02,0x08,0x04,0x02,0x08,0x04,0x04,0x10,0x03,0x08,0xF0,0x01,0xFF,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x00,0x70,0x38,0x00,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x1A,0x00,0x30,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x14,0x00,0x00,0x22,0x00,0x00,0x41,0x00,0x00,0x80,0x80,0x01,0x00,0x40,0x02,0x00,0x20,0x04,0x00,0x10,0x08,0x00,0x08,0x00,0x00,0x00},/*"<",28*/
{0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x04,0x00,0x10,0x02,0x00,0x20,0x01,0x00,0x40,0x00,0x80,0x80,0x00,0x41,0x00,0x00,0x22,0x00,0x00,0x14,0x00,0x00,0x08,0x00,0x00,0x00,0x00},/*">",30*/
{0x00,0x00,0x00,0x03,0xC0,0x00,0x04,0xC0,0x00,0x04,0x00,0x00,0x08,0x00,0x38,0x08,0x0F,0x38,0x08,0x08,0x38,0x08,0x10,0x00,0x0C,0x30,0x00,0x07,0xE0,0x00,0x03,0xC0,0x00,0x00,0x00,0x00},/*"?",31*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0xFF,0xE0,0x03,0x80,0x70,0x02,0x0F,0x10,0x06,0x70,0x88,0x04,0xC0,0x88,0x04,0x83,0x08,0x04,0x7F,0x88,0x02,0xC0,0x90,0x03,0x01,0x20,0x00,0xFE,0x40},/*"@",32*/
{0x00,0x00,0x08,0x00,0x00,0x18,0x00,0x01,0xF8,0x00,0x3E,0x08,0x01,0xC2,0x00,0x07,0x02,0x00,0x07,0xE2,0x00,0x00,0xFE,0x00,0x00,0x1F,0xC8,0x00,0x01,0xF8,0x00,0x00,0x38,0x00,0x00,0x08},/*"A",33*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x06,0x18,0x08,0x03,0xF4,0x18,0x01,0xE7,0xF0,0x00,0x01,0xE0,0x00,0x00,0x00},/*"B",34*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x02,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x10,0x06,0x00,0x20,0x07,0x80,0xC0,0x00,0x00,0x00},/*"C",35*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x18,0x02,0x00,0x10,0x03,0x80,0x70,0x01,0xFF,0xE0,0x00,0x7F,0x80,0x00,0x00,0x00},/*"D",36*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x3E,0x08,0x04,0x00,0x08,0x06,0x00,0x18,0x01,0x00,0x60,0x00,0x00,0x00},/*"E",37*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x00,0x04,0x08,0x00,0x04,0x08,0x00,0x04,0x3E,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00},/*"F",38*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x18,0x04,0x00,0x08,0x04,0x02,0x08,0x04,0x02,0x08,0x02,0x03,0xF0,0x07,0x83,0xF0,0x00,0x02,0x00,0x00,0x02,0x00},/*"G",39*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x04,0x08,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08},/*"H",40*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x01,0x04,0x00,0x01,0x04,0x00,0x01,0x04,0x00,0x03,0x07,0xFF,0xFE,0x07,0xFF,0xFC,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00},/*"J",42*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x0C,0x08,0x00,0x18,0x00,0x00,0x3E,0x00,0x04,0xC7,0x80,0x05,0x03,0xC8,0x06,0x00,0xF8,0x04,0x00,0x38,0x04,0x00,0x18,0x00,0x00,0x08},/*"K",43*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x00},/*"L",44*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0x80,0x08,0x07,0xFC,0x00,0x00,0x7F,0xC0,0x00,0x03,0xF8,0x00,0x07,0xC0,0x00,0x78,0x00,0x07,0x80,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08},/*"M",45*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0x00,0x08,0x03,0xC0,0x00,0x00,0xE0,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x07,0x00,0x00,0x01,0xC0,0x04,0x00,0xF0,0x07,0xFF,0xF8,0x04,0x00,0x00},/*"N",46*/
{0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x06,0x00,0x18,0x03,0x00,0x30,0x01,0xFF,0xE0,0x00,0x7F,0x80,0x00,0x00,0x00},/*"O",47*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x04,0x08,0x04,0x04,0x00,0x04,0x04,0x00,0x04,0x04,0x00,0x04,0x04,0x00,0x06,0x0C,0x00,0x03,0xF8,0x00,0x01,0xF0,0x00,0x00,0x00,0x00},/*"P",48*/
{0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x88,0x04,0x00,0x88,0x04,0x00,0xC8,0x06,0x00,0x3C,0x03,0x00,0x3E,0x01,0xFF,0xE6,0x00,0x7F,0x84,0x00,0x00,0x00},/*"Q",49*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x00,0x04,0x0C,0x00,0x04,0x0F,0x00,0x04,0x0B,0xC0,0x06,0x10,0xF0,0x03,0xF0,0x38,0x01,0xE0,0x08,0x00,0x00,0x08},/*"R",50*/
{0x00,0x00,0x00,0x01,0xE0,0xF8,0x03,0xF0,0x30,0x06,0x30,0x10,0x04,0x18,0x08,0x04,0x18,0x08,0x04,0x0C,0x08,0x04,0x0C,0x08,0x02,0x06,0x18,0x02,0x07,0xF0,0x07,0x81,0xE0,0x00,0x00,0x00},/*"S",51*/
{0x01,0x80,0x00,0x06,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x04,0x00,0x00,0x04,0x00,0x00,0x06,0x00,0x00,0x01,0x80,0x00},/*"T",52*/
{0x04,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xF0,0x04,0x00,0x18,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x04,0x00,0x10,0x07,0xFF,0xE0,0x04,0x00,0x00},/*"U",53*/
{0x04,0x00,0x00,0x06,0x00,0x00,0x07,0xE0,0x00,0x07,0xFE,0x00,0x04,0x1F,0xE0,0x00,0x01,0xF8,0x00,0x00,0x38,0x00,0x01,0xE0,0x04,0x3E,0x00,0x07,0xC0,0x00,0x06,0x00,0x00,0x04,0x00,0x00},/*"V",54*/
{0x04,0x00,0x00,0x07,0xE0,0x00,0x07,0xFF,0xC0,0x04,0x1F,0xF8,0x00,0x07,0xC0,0x07,0xF8,0x00,0x07,0xFF,0x80,0x04,0x3F,0xF8,0x00,0x07,0xC0,0x04,0xF8,0x00,0x07,0x00,0x00,0x04,0x00,0x00},/*"W",55*/
{0x00,0x00,0x00,0x04,0x00,0x08,0x06,0x00,0x18,0x07,0xC0,0x78,0x05,0xF1,0xC8,0x00,0x3E,0x00,0x00,0x1F,0x80,0x04,0x63,0xE8,0x07,0x80,0xF8,0x06,0x00,0x18,0x04,0x00,0x08,0x00,0x00,0x00},/*"X",56*/
{0x04,0x00,0x00,0x06,0x00,0x00,0x07,0x80,0x00,0x07,0xE0,0x08,0x04,0x7C,0x08,0x00,0x1F,0xF8,0x00,0x07,0xF8,0x00,0x18,0x08,0x04,0xE0,0x08,0x07,0x00,0x00,0x06,0x00,0x00,0x04,0x00,0x00},/*"Y",57*/
{0x00,0x00,0x00,0x01,0x00,0x08,0x06,0x00,0x38,0x04,0x00,0xF8,0x04,0x03,0xE8,0x04,0x0F,0x08,0x04,0x7C,0x08,0x05,0xF0,0x08,0x07,0xC0,0x08,0x07,0x00,0x18,0x04,0x00,0x60,0x00,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFE,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x00,0x00,0x00},/*"[",59*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x07,0x00,0x00,0x00,0xC0,0x00,0x00,0x38,0x00,0x00,0x06,0x00,0x00,0x01,0xC0,0x00,0x00,0x30,0x00,0x00,0x0E,0x00,0x00,0x01,0x00,0x00,0x00},/*"\",60*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x3F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x10,0x00,0x00,0x30,0x00,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01},/*"_",63*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x19,0xF8,0x00,0x1B,0x18,0x00,0x22,0x08,0x00,0x26,0x08,0x00,0x24,0x08,0x00,0x24,0x10,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x00,0x08,0x00,0x00,0x18},/*"a",65*/
{0x00,0x00,0x00,0x04,0x00,0x00,0x07,0xFF,0xF8,0x0F,0xFF,0xF0,0x00,0x18,0x18,0x00,0x10,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x30,0x18,0x00,0x1F,0xF0,0x00,0x0F,0xC0,0x00,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x18,0x30,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x3C,0x08,0x00,0x1C,0x10,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x38,0x18,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x04,0x10,0x10,0x07,0xFF,0xF8,0x0F,0xFF,0xF0,0x00,0x00,0x10,0x00,0x00,0x00},/*"d",68*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x12,0x30,0x00,0x22,0x18,0x00,0x22,0x08,0x00,0x22,0x08,0x00,0x32,0x08,0x00,0x1E,0x10,0x00,0x0E,0x20,0x00,0x00,0x00},/*"e",69*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x08,0x00,0x20,0x08,0x01,0xFF,0xF8,0x03,0xFF,0xF8,0x06,0x20,0x08,0x04,0x20,0x08,0x04,0x20,0x08,0x07,0x20,0x00,0x03,0x00,0x00,0x00,0x00,0x00},/*"f",70*/
{0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x6E,0x00,0x1F,0xF3,0x00,0x31,0xB1,0x00,0x20,0xB1,0x00,0x20,0xB1,0x00,0x31,0x91,0x00,0x1F,0x13,0x00,0x2E,0x1E,0x00,0x20,0x0E,0x00,0x30,0x00},/*"g",71*/
{0x00,0x00,0x00,0x04,0x00,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x10,0x08,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x00,0x08,0x00,0x00,0x00},/*"h",72*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x06,0x3F,0xF8,0x06,0x3F,0xF8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x20,0x01,0x00,0x20,0x01,0x00,0x20,0x03,0x06,0x3F,0xFE,0x06,0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"j",74*/
{0x00,0x00,0x00,0x04,0x00,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x01,0x88,0x00,0x03,0x00,0x00,0x2F,0xC0,0x00,0x38,0xF8,0x00,0x20,0x38,0x00,0x20,0x08,0x00,0x00,0x08,0x00,0x00,0x00},/*"k",75*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"l",76*/
{0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x10,0x08,0x00,0x20,0x00,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x10,0x08,0x00,0x20,0x00,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x00,0x08},/*"m",77*/
{0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x10,0x08,0x00,0x10,0x00,0x00,0x20,0x00,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x00,0x08,0x00,0x00,0x00},/*"n",78*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x0F,0xF0,0x00,0x18,0x30,0x00,0x30,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x30,0x08,0x00,0x18,0x30,0x00,0x0F,0xF0,0x00,0x07,0xC0,0x00,0x00,0x00},/*"o",79*/
{0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x3F,0xFF,0x00,0x3F,0xFF,0x00,0x10,0x11,0x00,0x20,0x09,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x30,0x38,0x00,0x1F,0xF0,0x00,0x0F,0xC0,0x00,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x38,0x18,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x09,0x00,0x10,0x11,0x00,0x1F,0xFF,0x00,0x3F,0xFF,0x00,0x00,0x01,0x00,0x00,0x00},/*"q",81*/
{0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x08,0x08,0x00,0x10,0x08,0x00,0x20,0x08,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x78,0x00,0x1E,0x18,0x00,0x33,0x08,0x00,0x23,0x08,0x00,0x21,0x08,0x00,0x21,0x88,0x00,0x21,0x98,0x00,0x30,0xF0,0x00,0x38,0x60,0x00,0x00,0x00},/*"s",83*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0xFF,0xF0,0x03,0xFF,0xF8,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00},/*"t",84*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x3F,0xF0,0x00,0x7F,0xF8,0x00,0x00,0x18,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x20,0x10,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0x00,0x10,0x00,0x00,0x00},/*"u",85*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x3C,0x00,0x00,0x3F,0x80,0x00,0x23,0xF0,0x00,0x00,0x78,0x00,0x00,0x70,0x00,0x23,0x80,0x00,0x3C,0x00,0x00,0x30,0x00,0x00,0x20,0x00},/*"v",86*/
{0x00,0x20,0x00,0x00,0x3C,0x00,0x00,0x3F,0xE0,0x00,0x23,0xF8,0x00,0x00,0xE0,0x00,0x27,0x00,0x00,0x3E,0x00,0x00,0x3F,0xE0,0x00,0x21,0xF8,0x00,0x01,0xE0,0x00,0x3E,0x00,0x00,0x20,0x00},/*"w",87*/
{0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x38,0x38,0x00,0x3E,0x68,0x00,0x27,0x80,0x00,0x03,0xC8,0x00,0x2C,0xF8,0x00,0x38,0x38,0x00,0x20,0x18,0x00,0x20,0x08,0x00,0x00,0x00},/*"x",88*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x30,0x03,0x00,0x3C,0x01,0x00,0x3F,0x83,0x00,0x23,0xEC,0x00,0x00,0x70,0x00,0x23,0x80,0x00,0x3C,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"y",89*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x08,0x00,0x20,0x38,0x00,0x20,0xF8,0x00,0x23,0xE8,0x00,0x2F,0x88,0x00,0x3E,0x08,0x00,0x38,0x08,0x00,0x20,0x18,0x00,0x00,0x70,0x00,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x14,0x00,0x1F,0xF7,0xFC,0x30,0x00,0x06,0x20,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x02,0x30,0x00,0x06,0x1F,0xF7,0xFC,0x00,0x14,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x0C,0x00,0x00,0x10,0x00,0x00},/*"~",94*/
};
//32*32 ASCII字符集点阵
const unsigned char asc2_3216[95][128]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0xC0,0x07,0xFF,0xE1,0xE0,0x07,0xF0,0x01,0xE0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x1C,0x20,0x00,0x00,0x01,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0F,0xE0,0x00,0x1F,0xFC,0x00,0x03,0xF8,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0F,0xE0,0x00,0x1F,0xFC,0x00,0x03,0xF8,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x00,0x00,0x00},/*"#",3*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x78,0x07,0xC0,0x00,0xFC,0x06,0x40,0x01,0x0E,0x00,0x20,0x03,0x07,0x00,0x20,0x02,0x03,0x80,0x20,0x0F,0xFF,0xFF,0xFC,0x02,0x01,0xC0,0x20,0x02,0x00,0xE0,0x60,0x01,0x30,0x70,0x40,0x01,0xF0,0x3F,0x80,0x00,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"$",4*/
{0x00,0xFE,0x00,0x00,0x01,0xFF,0x00,0x00,0x03,0x01,0x80,0x00,0x02,0x00,0x80,0x60,0x03,0x01,0x81,0xC0,0x01,0xFF,0x07,0x00,0x00,0xFE,0x18,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0xBF,0x00,0x00,0x0C,0xFF,0xC0,0x00,0x71,0x80,0x60,0x01,0xC1,0x00,0x20,0x03,0x01,0x80,0x60,0x00,0x00,0xFF,0xC0,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00},/*"%",5*/
{0x00,0x00,0x1F,0x00,0x00,0x00,0x7F,0xC0,0x00,0xFC,0xC0,0xC0,0x01,0xFF,0x80,0x60,0x03,0x03,0xE0,0x20,0x02,0x02,0x78,0x20,0x02,0x06,0x1E,0x20,0x03,0xFC,0x07,0x40,0x01,0xF0,0x03,0x80,0x00,0x01,0x03,0xC0,0x00,0x01,0x1C,0x60,0x00,0x01,0xE0,0x20,0x00,0x01,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00},/*"&",6*/
{0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x1C,0x60,0x00,0x00,0x1C,0x40,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x3F,0xFF,0x00,0x00,0x78,0x07,0xC0,0x01,0xC0,0x00,0xE0,0x03,0x00,0x00,0x30,0x04,0x00,0x00,0x08,0x08,0x00,0x00,0x04,0x10,0x00,0x00,0x02,0x00,0x00,0x00,0x00},/*"(",8*/
{0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0x08,0x00,0x00,0x04,0x04,0x00,0x00,0x08,0x03,0x00,0x00,0x30,0x01,0xC0,0x00,0xE0,0x00,0x78,0x07,0xC0,0x00,0x3F,0xFF,0x00,0x00,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x00,0x00,0x0E,0x38,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x03,0x60,0x00,0x00,0x61,0x43,0x80,0x00,0xFF,0xFF,0x80,0x00,0x61,0x43,0x00,0x00,0x03,0x60,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x0E,0x38,0x00,0x00,0x0C,0x18,0x00,0x00,0x00,0x00,0x00},/*"*",10*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},/*"+",11*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xE3,0x00,0x00,0x00,0xE2,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x0E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x0E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x0E,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"/",15*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x7F,0xFF,0x00,0x00,0xF0,0x07,0x80,0x01,0x80,0x00,0xC0,0x03,0x00,0x00,0x60,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0x00,0x00,0x60,0x01,0x80,0x00,0xC0,0x00,0xE0,0x03,0x80,0x00,0x7F,0xFF,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00},/*"0",16*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x60,0x01,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0xE0,0x00,0x98,0x01,0x60,0x01,0x00,0x02,0x60,0x02,0x00,0x04,0x60,0x02,0x00,0x08,0x60,0x02,0x00,0x10,0x60,0x02,0x00,0x20,0x60,0x02,0x00,0x40,0x60,0x03,0x00,0x80,0x60,0x01,0x83,0x00,0x60,0x01,0xFE,0x00,0xE0,0x00,0x7C,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",18*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x80,0x01,0xF0,0x07,0xC0,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x03,0x03,0x80,0x20,0x01,0x86,0x80,0x40,0x01,0xFC,0xC0,0xC0,0x00,0x78,0x7F,0x80,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x48,0x00,0x00,0x01,0x88,0x00,0x00,0x06,0x08,0x00,0x00,0x0C,0x08,0x10,0x00,0x30,0x08,0x10,0x00,0x40,0x08,0x10,0x01,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xF0,0x00,0x00,0x08,0x10,0x00,0x00,0x08,0x10,0x00,0x00,0x08,0x10,0x00,0x00,0x00,0x00},/*"4",20*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x1F,0x86,0x40,0x03,0xE1,0x00,0x20,0x03,0x02,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x06,0x00,0x40,0x03,0x03,0x01,0xC0,0x03,0x01,0xFF,0x80,0x03,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",21*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFC,0x00,0x00,0x3F,0xFF,0x00,0x00,0x70,0xC3,0x80,0x00,0x81,0x80,0xC0,0x01,0x01,0x00,0x60,0x03,0x02,0x00,0x20,0x02,0x02,0x00,0x20,0x02,0x02,0x00,0x20,0x02,0x02,0x00,0x20,0x02,0x03,0x00,0x40,0x01,0xC1,0x80,0xC0,0x00,0xC0,0xFF,0x80,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"6",22*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x07,0xE0,0x03,0x00,0x3F,0xE0,0x03,0x01,0xC0,0x00,0x03,0x06,0x00,0x00,0x03,0x18,0x00,0x00,0x03,0x60,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x78,0x3F,0x80,0x00,0xFC,0x60,0xC0,0x01,0x8E,0xC0,0x40,0x03,0x07,0x80,0x20,0x02,0x03,0x00,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0xC0,0x20,0x03,0x01,0xE0,0x40,0x01,0x86,0x70,0xC0,0x00,0xFC,0x3F,0x80,0x00,0x78,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"8",24*/
{0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0xFF,0x81,0xC0,0x01,0xC0,0xC1,0xC0,0x01,0x00,0x60,0x20,0x02,0x00,0x20,0x20,0x02,0x00,0x20,0x20,0x02,0x00,0x20,0x20,0x02,0x00,0x20,0x60,0x02,0x00,0x40,0xC0,0x01,0x00,0xC1,0x80,0x00,0xC1,0x8F,0x00,0x00,0x7F,0xFE,0x00,0x00,0x1F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xC0,0x00,0x07,0x81,0xE0,0x00,0x07,0x81,0xE0,0x00,0x03,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x66,0x00,0x06,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x01,0xC0,0x00,0x00,0x03,0x60,0x00,0x00,0x06,0x30,0x00,0x00,0x0C,0x18,0x00,0x00,0x18,0x0C,0x00,0x00,0x30,0x06,0x00,0x00,0x60,0x03,0x00,0x00,0xC0,0x01,0x80,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"<",28*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x10,0x02,0x00,0x00,0x20,0x01,0x00,0x00,0x40,0x00,0xC0,0x01,0x80,0x00,0x60,0x03,0x00,0x00,0x30,0x06,0x00,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x03,0x60,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*">",30*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x02,0x38,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0xC0,0x04,0x00,0x79,0xE0,0x04,0x00,0x81,0xE0,0x04,0x01,0x00,0xC0,0x04,0x03,0x00,0x00,0x02,0x02,0x00,0x00,0x03,0x06,0x00,0x00,0x01,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00},/*"?",31*/
{0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xFE,0x00,0x00,0x70,0x07,0x80,0x00,0xC0,0x00,0xC0,0x01,0x01,0xF8,0x40,0x03,0x07,0xFC,0x20,0x02,0x1E,0x04,0x20,0x02,0x30,0x08,0x20,0x02,0x20,0x30,0x20,0x02,0x3F,0xFC,0x20,0x01,0x3F,0x04,0x40,0x01,0x80,0x0C,0xC0,0x00,0xE0,0x31,0x80,0x00,0x1F,0xC2,0x00,0x00,0x00,0x00,0x00},/*"@",32*/
{0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x03,0xE0,0x00,0x00,0x3E,0x20,0x00,0x03,0xE0,0x20,0x00,0x3E,0x20,0x00,0x03,0xE0,0x20,0x00,0x03,0x80,0x20,0x00,0x07,0xFC,0x20,0x00,0x00,0x3F,0xE0,0x00,0x00,0x03,0xFE,0x20,0x00,0x00,0x3F,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"A",33*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x03,0x03,0x00,0x20,0x01,0x86,0x80,0x60,0x01,0xFC,0xC0,0xC0,0x00,0xF8,0x7F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00},/*"B",34*/
{0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x3F,0xFF,0x00,0x00,0x70,0x07,0x80,0x00,0xC0,0x00,0xC0,0x01,0x00,0x00,0x40,0x03,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x01,0x00,0x00,0x40,0x01,0x80,0x00,0xC0,0x03,0xC0,0x01,0x80,0x00,0x30,0x06,0x00,0x00,0x00,0x00,0x00},/*"C",35*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0x00,0x00,0x60,0x01,0x00,0x00,0x40,0x01,0x80,0x00,0xC0,0x00,0xF0,0x07,0x80,0x00,0x7F,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00},/*"D",36*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x03,0x80,0x20,0x02,0x0F,0xE0,0x20,0x03,0x00,0x00,0x60,0x03,0xC0,0x00,0xE0,0x00,0x60,0x03,0x00,0x00,0x00,0x00,0x00},/*"E",37*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x02,0x03,0x80,0x00,0x03,0x0F,0xE0,0x00,0x03,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x60,0x00,0x00},/*"F",38*/
{0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x3F,0xFE,0x00,0x00,0x70,0x07,0x80,0x01,0xC0,0x01,0xC0,0x01,0x00,0x00,0x40,0x03,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x01,0x00,0x20,0x20,0x01,0x00,0x20,0x40,0x03,0xC0,0x3F,0x80,0x00,0x30,0x3F,0x80,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00},/*"G",39*/
{0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x20,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"H",40*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x03,0x02,0x00,0x00,0x06,0x03,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xF8,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"J",42*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0xC0,0x20,0x02,0x01,0x00,0x20,0x00,0x07,0x80,0x00,0x00,0x0F,0xE0,0x00,0x00,0x30,0xF8,0x00,0x02,0x60,0x3E,0x20,0x03,0x80,0x0F,0x20,0x03,0x00,0x03,0xE0,0x02,0x00,0x00,0xE0,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x20},/*"K",43*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00},/*"L",44*/
{0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xE0,0x00,0x20,0x03,0xFF,0x00,0x20,0x00,0x1F,0xF0,0x00,0x00,0x01,0xFF,0x80,0x00,0x00,0x0F,0xE0,0x00,0x00,0x1E,0x00,0x00,0x03,0xE0,0x00,0x00,0x3E,0x00,0x20,0x03,0xE0,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20},/*"M",45*/
{0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0x80,0x00,0x20,0x03,0xF0,0x00,0x20,0x00,0xFC,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x7C,0x00,0x02,0x00,0x1F,0x80,0x02,0x00,0x07,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"N",46*/
{0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xFE,0x00,0x00,0xF0,0x07,0x80,0x01,0x80,0x00,0xC0,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x01,0x00,0x00,0x40,0x01,0x80,0x00,0xC0,0x00,0xF0,0x03,0x80,0x00,0x3F,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00},/*"O",47*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x00,0x02,0x00,0x80,0x00,0x02,0x00,0x80,0x00,0x02,0x00,0x80,0x00,0x03,0x01,0x80,0x00,0x01,0x83,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00},/*"P",48*/
{0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x7F,0xFF,0x00,0x00,0xF0,0x03,0x80,0x01,0x80,0x01,0xC0,0x01,0x00,0x06,0x40,0x02,0x00,0x04,0x20,0x02,0x00,0x04,0x20,0x02,0x00,0x06,0x20,0x02,0x00,0x03,0xE0,0x01,0x00,0x00,0xF8,0x01,0x80,0x00,0x5C,0x00,0xE0,0x03,0x8C,0x00,0x3F,0xFF,0x0C,0x00,0x0F,0xFC,0x18,0x00,0x00,0x00,0x00},/*"Q",49*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x80,0x00,0x02,0x01,0xE0,0x00,0x02,0x01,0xFC,0x00,0x03,0x03,0x3F,0x80,0x01,0x86,0x07,0xE0,0x01,0xFC,0x00,0xE0,0x00,0xF8,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"R",50*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x06,0x00,0x00,0xFE,0x01,0xE0,0x01,0x86,0x00,0xC0,0x03,0x03,0x00,0x40,0x02,0x03,0x00,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0xC0,0x20,0x02,0x00,0xC0,0x20,0x01,0x00,0xE0,0x60,0x01,0x80,0x70,0xC0,0x03,0xE0,0x3F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00},/*"S",51*/
{0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*"T",52*/
{0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xC0,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x80,0x03,0xFF,0xFF,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"U",53*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xFC,0x00,0x00,0x02,0x3F,0xC0,0x00,0x00,0x03,0xF8,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0x80,0x00,0x00,0x78,0x00,0x02,0x03,0xC0,0x00,0x02,0x3C,0x00,0x00,0x03,0xC0,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00},/*"V",54*/
{0x02,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xFF,0x80,0x00,0x02,0x3F,0xFE,0x00,0x02,0x00,0x7F,0xE0,0x00,0x00,0x0F,0x00,0x02,0x00,0xF0,0x00,0x03,0xEF,0x00,0x00,0x03,0xFF,0x80,0x00,0x02,0x0F,0xFE,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x1F,0x00,0x02,0x07,0xE0,0x00,0x03,0xF8,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00},/*"W",55*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0x80,0x00,0xE0,0x03,0xF0,0x03,0x20,0x02,0xFC,0x0C,0x20,0x02,0x1F,0x30,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xF0,0x00,0x02,0x18,0x7C,0x00,0x02,0x60,0x1F,0x20,0x03,0x80,0x03,0xE0,0x02,0x00,0x00,0xE0,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"X",56*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xF8,0x00,0x00,0x02,0x3E,0x00,0x20,0x02,0x0F,0xC0,0x20,0x00,0x01,0xFF,0xE0,0x00,0x00,0x7F,0xE0,0x00,0x03,0x80,0x20,0x02,0x1C,0x00,0x20,0x02,0x70,0x00,0x00,0x03,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"Y",57*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0xE0,0x03,0x80,0x03,0xE0,0x03,0x00,0x0F,0xA0,0x02,0x00,0x3E,0x20,0x02,0x00,0xF8,0x20,0x02,0x03,0xE0,0x20,0x02,0x0F,0x80,0x20,0x02,0x3E,0x00,0x20,0x02,0x78,0x00,0x20,0x03,0xE0,0x00,0x60,0x03,0x80,0x00,0xE0,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFC,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"[",59*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"\",60*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x1F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01},/*"_",63*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x01,0x8F,0xC0,0x00,0x03,0x8C,0x60,0x00,0x06,0x18,0x20,0x00,0x04,0x10,0x20,0x00,0x04,0x10,0x20,0x00,0x04,0x20,0x20,0x00,0x04,0x20,0x40,0x00,0x06,0x20,0x40,0x00,0x03,0xFF,0xC0,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00},/*"a",65*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x00,0x01,0x80,0xC0,0x00,0x02,0x00,0x60,0x00,0x02,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x40,0x00,0x03,0x00,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x81,0xC0,0x00,0x02,0x00,0x40,0x00,0x06,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x03,0xC0,0x40,0x00,0x01,0xC0,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x80,0xC0,0x00,0x06,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x02,0x04,0x00,0x40,0x02,0x02,0x00,0x80,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00},/*"d",68*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x11,0xC0,0x00,0x02,0x10,0x40,0x00,0x04,0x10,0x60,0x00,0x04,0x10,0x20,0x00,0x04,0x10,0x20,0x00,0x04,0x10,0x20,0x00,0x06,0x10,0x20,0x00,0x03,0x10,0x40,0x00,0x01,0xF0,0xC0,0x00,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"e",69*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x7F,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,0x01,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x02,0x04,0x00,0x20,0x02,0x04,0x00,0x20,0x02,0x04,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00},/*"f",70*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0xE3,0x3E,0x00,0x03,0xFF,0xC2,0x00,0x02,0x0C,0xC3,0x00,0x04,0x04,0xC1,0x00,0x04,0x04,0xC1,0x00,0x04,0x04,0xC1,0x00,0x04,0x04,0xC1,0x00,0x06,0x0C,0xC1,0x00,0x03,0xF8,0xC3,0x00,0x05,0xF0,0x62,0x00,0x06,0x00,0x7E,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00},/*"g",71*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x01,0x00,0x20,0x00,0x02,0x00,0x20,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x03,0xFF,0xE0,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20},/*"h",72*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x03,0x87,0xFF,0xE0,0x03,0x8F,0xFF,0xE0,0x03,0x80,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x03,0x00,0x04,0x00,0x06,0x03,0x87,0xFF,0xFC,0x03,0x8F,0xFF,0xF8,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"j",74*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x08,0x20,0x00,0x00,0x10,0x20,0x00,0x00,0x30,0x00,0x00,0x00,0xFC,0x00,0x00,0x05,0x8E,0x00,0x00,0x07,0x07,0xA0,0x00,0x06,0x01,0xE0,0x00,0x04,0x00,0xE0,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"k",75*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"l",76*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0x00,0x02,0x00,0x20,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x02,0x00,0x20,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"m",77*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0x00,0x01,0x00,0x20,0x00,0x02,0x00,0x20,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x03,0xFF,0xE0,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20},/*"n",78*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xFF,0x80,0x00,0x03,0x81,0xC0,0x00,0x02,0x00,0x40,0x00,0x06,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x03,0x81,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"o",79*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x07,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0x00,0x01,0x00,0xC1,0x00,0x02,0x00,0x41,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x40,0x00,0x03,0x01,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x80,0xC0,0x00,0x02,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x41,0x00,0x03,0x00,0xC1,0x00,0x03,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01},/*"q",81*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x0F,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0x00,0x00,0xC0,0x20,0x00,0x01,0x00,0x20,0x00,0x02,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,0x01,0xC0,0xE0,0x00,0x03,0xE0,0x40,0x00,0x06,0x30,0x20,0x00,0x04,0x30,0x20,0x00,0x04,0x18,0x20,0x00,0x04,0x18,0x20,0x00,0x04,0x18,0x20,0x00,0x04,0x0C,0x20,0x00,0x02,0x0C,0x60,0x00,0x03,0x07,0xC0,0x00,0x07,0x83,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"s",83*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0xFF,0xFF,0xC0,0x00,0x04,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x40,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"t",84*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0xFF,0x80,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x40,0x00,0x04,0x00,0x80,0x00,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40},/*"u",85*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x07,0xF0,0x00,0x00,0x04,0xFE,0x00,0x00,0x04,0x1F,0xC0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x1C,0x00,0x00,0x04,0x60,0x00,0x00,0x07,0x80,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"v",86*/
{0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xFC,0x00,0x00,0x04,0x3F,0x80,0x00,0x00,0x03,0xE0,0x00,0x04,0x0F,0x80,0x00,0x06,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xFF,0x80,0x00,0x04,0x0F,0xE0,0x00,0x00,0x03,0x80,0x00,0x04,0x3C,0x00,0x00,0x07,0xC0,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00},/*"w",87*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x60,0x00,0x07,0x00,0xE0,0x00,0x07,0x83,0x20,0x00,0x07,0xE6,0x00,0x00,0x04,0xF8,0x00,0x00,0x00,0x3C,0x00,0x00,0x04,0x5E,0x20,0x00,0x05,0x87,0xA0,0x00,0x06,0x01,0xE0,0x00,0x04,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"x",88*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x03,0x00,0x07,0x00,0x03,0x00,0x07,0xE0,0x01,0x00,0x04,0xF8,0x01,0x00,0x04,0x1F,0x02,0x00,0x00,0x07,0xFC,0x00,0x00,0x00,0xE0,0x00,0x00,0x07,0x00,0x00,0x04,0x38,0x00,0x00,0x07,0xC0,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00},/*"y",89*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x60,0x00,0x06,0x00,0xE0,0x00,0x04,0x03,0xE0,0x00,0x04,0x07,0xA0,0x00,0x04,0x0E,0x20,0x00,0x04,0x3C,0x20,0x00,0x04,0x70,0x20,0x00,0x05,0xE0,0x20,0x00,0x07,0x80,0x20,0x00,0x07,0x00,0x60,0x00,0x04,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x01,0x40,0x00,0x07,0xFE,0x3F,0xF8,0x08,0x00,0x00,0x04,0x10,0x00,0x00,0x02,0x10,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0x10,0x00,0x00,0x02,0x08,0x00,0x00,0x04,0x07,0xFE,0x3F,0xF8,0x00,0x01,0x40,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/
};
#endif

View File

@@ -0,0 +1,61 @@
#include "bsp_led.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_led.c
作者 : 左忠凯
版本 : V1.0
描述 : LED驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
/*
* @description : 初始化LED对应的GPIO
* @param : 无
* @return : 无
*/
void led_init(void)
{
/* 1、初始化IO复用 */
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); /* 复用为GPIO1_IO03 */
/* 2、、配置GPIO1_IO03的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 R0/6驱动能力
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0);
/* 3、初始化GPIO,GPIO1_IO03设置为输出*/
GPIO1->GDIR |= (1 << 3);
/* 4、设置GPIO1_IO03输出低电平打开LED0*/
GPIO1->DR &= ~(1 << 3);
}
/*
* @description : LED控制函数控制LED打开还是关闭
* @param - led : 要控制的LED灯编号
* @param - status : 0关闭LED01 打开LED0
* @return : 无
*/
void led_switch(int led, int status)
{
switch(led)
{
case LED0:
if(status == ON)
GPIO1->DR &= ~(1<<3); /* 打开LED0 */
else if(status == OFF)
GPIO1->DR |= (1<<3); /* 关闭LED0 */
break;
}
}

View File

@@ -0,0 +1,21 @@
#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "bsp.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_led.h
作者 : 左忠凯
版本 : V1.0
描述 : LED驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#define LED0 0
/* 函数声明 */
void led_init(void);
void led_switch(int led, int status);
#endif

View File

@@ -0,0 +1,236 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_mpu9250.c
作者 : 左忠凯
版本 : V1.0
描述 : MPU9250驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
#include "bsp_mpu9250.h"
#include "bsp_i2c.h"
#include "bsp_delay.h"
#include "printf.h"
/*
* @description : 初始化MPU9250
* @param : 无
* @return : 0 成功,其他值 错误代码
*/
unsigned char mpu9250_init(void)
{
unsigned char data = 0;
i2c_init(); /* 初始化IIC */
mpu_write_byte(MPU9250_ADDR,MPU_PWR_MGMT1_REG,0X80);//复位MPU9250
delayms(100); //延时100ms
mpu_write_byte(MPU9250_ADDR,MPU_PWR_MGMT1_REG,0X00);//唤醒MPU9250
mpu_set_gyro_range(3); //陀螺仪传感器,±2000dps
mpu_set_accel_range(0); //加速度传感器,±2g
mpu_set_rate(50); //设置采样率50Hz
mpu_write_byte(MPU9250_ADDR,MPU_INT_EN_REG,0X00); //关闭所有中断
mpu_write_byte(MPU9250_ADDR,MPU_USER_CTRL_REG,0X00);//I2C主模式关闭
mpu_write_byte(MPU9250_ADDR,MPU_FIFO_EN_REG,0X00); //关闭FIFO
mpu_write_byte(MPU9250_ADDR,MPU_INTBP_CFG_REG,0X82);//INT引脚低电平有效开启bypass模式可以直接读取磁力计
data = mpu_read_byte(MPU9250_ADDR,MPU_DEVICE_ID_REG);
if(data == MPU6500_ID)
{
printf("MPU9250 ID=%#X\r\n", data);
mpu_write_byte(MPU9250_ADDR, MPU_PWR_MGMT1_REG, 0X01); /* 设置CLKSEL,PLL X轴为参考 */
mpu_write_byte(MPU9250_ADDR, MPU_PWR_MGMT2_REG, 0X00); /* 加速度与陀螺仪都工作 */
mpu_set_rate(50); /* 设置采样率为50Hz */
}
else {
return 1;
}
data = mpu_read_byte(AK8963_ADDR, MAG_WIA); /* 读取AK8963 ID */
if(data == AK8963_ID)
{
printf("AK8963_ID=%#X\r\n", data);
mpu_write_byte(AK8963_ADDR, MAG_CNTL1, 0X11); /* 设置AK8963为单次测量模式 */
}else return 2;
return 0;
}
/*
* @description : 向MPU9250写入数据
* @param - addr: 设备地址
* @param - reg : 要写入的寄存器
* @param - data: 要写入的数据
* @return : 操作结果
*/
unsigned char mpu_write_byte(unsigned char addr,unsigned char reg, unsigned char data)
{
unsigned char status=0;
unsigned char writedata=data;
struct i2c_transfer masterXfer;
/* 配置I2C xfer结构体 */
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Write; /* 写入数据 */
masterXfer.subaddress = reg; /* 要写入的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = &writedata; /* 要写入的数据 */
masterXfer.dataSize = 1; /* 写入数据长度1个字节 */
if(i2c_master_transfer(&masterXfer))
status=1;
return status;
}
/*
* @description : 从MPU9250读取一个字节的数据
* @param - addr: 设备地址
* @param - reg : 要读取的寄存器
* @return : 读取到的数据。
*/
unsigned char mpu_read_byte(unsigned char addr,unsigned char reg)
{
unsigned char val=0;
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Read; /* 读取数据 */
masterXfer.subaddress = reg; /* 要读取的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = &val; /* 接收数据缓冲区 */
masterXfer.dataSize = 1; /* 读取数据长度1个字节 */
i2c_master_transfer(&masterXfer);
return val;
}
/*
* @description : 从MPU9250读取多个字节的数据
* @param - addr: 设备地址
* @param - reg : 要读取的开始寄存器地址
* @param - len : 要读取的数据长度.
* @param - buf : 读取到的数据缓冲区
* @return : 无
*/
void mpu_read_len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf)
{
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Read; /* 读取数据 */
masterXfer.subaddress = reg; /* 要读取的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = buf; /* 接收数据缓冲区 */
masterXfer.dataSize = len; /* 读取数据长度1个字节 */
i2c_master_transfer(&masterXfer);
}
/*
* @description : 设置MPU9250陀螺仪量程
* @param - range : 量程范围,0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
* @return : 操作结果 0,设置成功 其他,设置失败
*/
unsigned char mpu_set_gyro_range(unsigned char range)
{
return mpu_write_byte(MPU9250_ADDR, MPU_GYRO_CFG_REG, range << 3);//设置陀螺仪满量程范围
}
/*
* @description : 设置MPU9250加速度量程
* @param - range : 量程范围,0,±2g;1,±4g;2,±8g;3,±16g
* @return : 操作结果 0,设置成功 其他,设置失败
*/
unsigned char mpu_set_accel_range(unsigned char range)
{
return mpu_write_byte(MPU9250_ADDR, MPU_ACCEL_CFG_REG,range << 3);//设置加速度传感器满量程范围
}
/*
* @description : 设置MPU9250的数字低通滤波器
* @param - range : 数字低通滤波频率(Hz)
* @return : 操作结果 0,设置成功 其他,设置失败
*/
unsigned char mpu_set_lpf(unsigned short fre)
{
unsigned char data = 0;
if(fre >= 188) data=1;
else if(fre >= 98) data=2;
else if(fre >= 42) data=3;
else if(fre >= 20) data=4;
else if(fre >= 10) data=5;
else data = 6;
return mpu_write_byte(MPU9250_ADDR,MPU_CFG_REG,data);
}
/*
* @description : 设置MPU9250采样率(假定Fs=1KHz)
* @param - rate: 4~1000(Hz)
* @return : 操作结果 0,设置成功 其他,设置失败
*/
unsigned char mpu_set_rate(unsigned short rate)
{
unsigned char data;
if(rate > 1000) rate = 1000;
if(rate < 4) rate = 4;
data = 1000 / rate - 1;
data = mpu_write_byte(MPU9250_ADDR,MPU_SAMPLE_RATE_REG,data); /* 设置数字低通滤波器 */
return mpu_set_lpf(rate / 2); /* 自动设置LPF为采样率的一半 */
}
/*
* @description : 得到陀螺仪值(原始值)
* @param - gx : 陀螺仪X轴原始数据
* @param - gy : 陀螺仪Y轴原始数据
* @param - gz 陀螺仪Z轴原始数据
* @return : 0,设置成功 其他,设置失败
*/
void mpu_get_gyroscope(short *gx,short *gy,short *gz)
{
unsigned char buf[6];
mpu_read_len(MPU9250_ADDR, MPU_GYRO_XOUTH_REG, 6, buf);
*gx=((short)buf[0] << 8) | buf[1];
*gy=((short)buf[2] << 8) | buf[3];
*gz=((short)buf[4] << 8) | buf[5];
}
/*
* @description : 得到加速度原始值
* @param - ax : 加速度X轴原始数据
* @param - ay : 加速度Y轴原始数据
* @param - az 加速度Z轴原始数据
* @return : 0,设置成功 其他,设置失败
*/
void mpu_get_accelerometer(short *ax,short *ay,short *az)
{
unsigned char buf[6];
mpu_read_len(MPU9250_ADDR, MPU_ACCEL_XOUTH_REG, 6, buf);
*ax=((short)buf[0] << 8) | buf[1];
*ay=((short)buf[2] << 8) | buf[3];
*az=((short)buf[4] << 8) | buf[5];
}
/*
* @description : 得到原始磁力计值
* @param - mx : 磁力计X轴原始数据
* @param - my : 磁力计Y轴原始数据
* @param - mz 磁力计Z轴原始数据
* @return : 0,设置成功 其他,设置失败
*/
void mpu_get_magnetometer(short *mx, short *my, short *mz)
{
unsigned char buf[6];
mpu_read_len(AK8963_ADDR, MAG_XOUT_L , 6, buf);
*mx = ((short)buf[1] << 8) | buf[0];
*my = ((short)buf[3] << 8) | buf[2];
*mz = ((short)buf[5] << 8) | buf[4];
mpu_write_byte(AK8963_ADDR, MAG_CNTL1, 0X11); /* AK8963每次读完以后都需要重新设置为单次测量模式 */
}

View File

@@ -0,0 +1,116 @@
#ifndef _BSP_MPU9250_H
#define _BSP_MPU9250_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_mpu9250.h
作者 : 左忠凯
版本 : V1.0
描述 : MPU9250驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp.h"
#define MPU9250_ADDR 0X68 /* MPU6500的器件IIC地址 */
#define MPU6500_ID 0X71 /* MPU6500的器件ID */
/*MPU9250内部封装了一个AK8963磁力计,地址和ID如下: */
#define AK8963_ADDR 0X0C /* AK8963的I2C地址 */
#define AK8963_ID 0X48 /* AK8963的器件ID */
/* MPU6500的内部寄存器 */
#define MPU_SELF_TESTX_REG 0X0D //自检寄存器X
#define MPU_SELF_TESTY_REG 0X0E //自检寄存器Y
#define MPU_SELF_TESTZ_REG 0X0F //自检寄存器Z
#define MPU_SELF_TESTA_REG 0X10 //自检寄存器A
#define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
#define MPU_CFG_REG 0X1A //配置寄存器
#define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
#define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG 0X24 //IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG 0X25 //IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG 0X26 //IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG 0X27 //IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG 0X28 //IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG 0X29 //IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG 0X2A //IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG 0X2B //IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG 0X2C //IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG 0X2D //IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG 0X2E //IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG 0X2F //IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG 0X30 //IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG 0X31 //IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG 0X32 //IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG 0X33 //IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG 0X34 //IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG 0X35 //IIC从机4读数据寄存器
#define MPU_I2CMST_STA_REG 0X36 //IIC主机状态寄存器
#define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
#define MPU_INT_EN_REG 0X38 //中断使能寄存器
#define MPU_INT_STA_REG 0X3A //中断状态寄存器
#define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器
#define MPU_TEMP_OUTH_REG 0X41 //温度值高八位寄存器
#define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器
#define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器
#define MPU_I2CSLV0_DO_REG 0X63 //IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG 0X64 //IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG 0X65 //IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG 0X66 //IIC从机3数据寄存器
#define MPU_I2CMST_DELAY_REG 0X67 //IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
#define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
#define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
#define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
#define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
#define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器
/*AK8963的内部寄存器 */
#define MAG_WIA 0x00 //AK8963的器件ID寄存器地址
#define MAG_CNTL1 0X0A
#define MAG_CNTL2 0X0B
#define MAG_XOUT_L 0X03
#define MAG_XOUT_H 0X04
#define MAG_YOUT_L 0X05
#define MAG_YOUT_H 0X06
#define MAG_ZOUT_L 0X07
#define MAG_ZOUT_H 0X08
/* 函数声明 */
unsigned char mpu9250_init(void);
unsigned char mpu_write_byte(unsigned char addr,unsigned char reg, unsigned char data);
unsigned char mpu_read_byte(unsigned char addr,unsigned char reg);
void mpu_read_Len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf);
unsigned char mpu_set_gyro_range(unsigned char range);
unsigned char mpu_set_accel_range(unsigned char range);
unsigned char mpu_set_lpf(unsigned short fre);
unsigned char mpu_set_rate(unsigned short rate);
void mpu_get_gyroscope(short *gx,short *gy,short *gz);
void mpu_get_accelerometer(short *ax,short *ay,short *az);
void mpu_get_magnetometer(short *mx, short *my, short *mz);
#endif

View File

@@ -0,0 +1,230 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_rtc.c
作者 : 左忠凯
版本 : V1.0
描述 : RTC驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
#include "bsp_rtc.h"
#include "printf.h"
/*
* 描述:初始化RTC
*/
void rtc_init(void)
{
/*
* 设置HPCOMR寄存器
* bit[31] 1 : 允许访问SNVS寄存器一定要置1
* bit[8] 1 : 此位置1需要签署NDA协议才能看到此位的详细说明
* 这里不置1也没问题
*/
SNVS->HPCOMR |= (1 << 31) | (1 << 8);
#if 0
struct rtc_datetime rtcdate;
rtcdate.year = 2018U;
rtcdate.month = 12U;
rtcdate.day = 13U;
rtcdate.hour = 14U;
rtcdate.minute = 52;
rtcdate.second = 0;
rtc_setDatetime(&rtcdate); //初始化时间和日期
#endif
rtc_enable(); //使能RTC
}
/*
* 描述: 开启RTC
*/
void rtc_enable(void)
{
/*
* LPCR寄存器bit0置1使能RTC
*/
SNVS->LPCR |= 1 << 0;
while(!(SNVS->LPCR & 0X01));//等待使能完成
}
/*
* 描述: 关闭RTC
*/
void rtc_disable(void)
{
/*
* LPCR寄存器bit0置0关闭RTC
*/
SNVS->LPCR &= ~(1 << 0);
while(SNVS->LPCR & 0X01);//等待关闭完成
}
/*
* @description : 判断指定年份是否为闰年,闰年条件如下:
* @param - year: 要判断的年份
* @return : 1 是闰年0 不是闰年
*/
unsigned char rtc_isleapyear(unsigned short year)
{
unsigned char value=0;
if(year % 400 == 0)
value = 1;
else
{
if((year % 4 == 0) && (year % 100 != 0))
value = 1;
else
value = 0;
}
return value;
}
/*
* @description : 将时间转换为秒数
* @param - datetime: 要转换日期和时间。
* @return : 转换后的秒数
*/
unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime)
{
unsigned short i = 0;
unsigned int seconds = 0;
unsigned int days = 0;
unsigned short monthdays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
for(i = 1970; i < datetime->year; i++)
{
days += DAYS_IN_A_YEAR; /* 平年每年365天 */
if(rtc_isleapyear(i)) days += 1;/* 闰年多加一天 */
}
days += monthdays[datetime->month];
if(rtc_isleapyear(i) && (datetime->month >= 3)) days += 1;/* 闰年并且当前月份大于等于3月的话加一天 */
days += datetime->day - 1;
seconds = days * SECONDS_IN_A_DAY +
datetime->hour * SECONDS_IN_A_HOUR +
datetime->minute * SECONDS_IN_A_MINUTE +
datetime->second;
return seconds;
}
/*
* @description : 设置时间和日期
* @param - datetime: 要设置的日期和时间
* @return : 无
*/
void rtc_setdatetime(struct rtc_datetime *datetime)
{
unsigned int seconds = 0;
unsigned int tmp = SNVS->LPCR;
rtc_disable(); /* 设置寄存器HPRTCMR和HPRTCLR的时候一定要先关闭RTC */
/* 先将时间转换为秒 */
seconds = rtc_coverdate_to_seconds(datetime);
SNVS->LPSRTCMR = (unsigned int)(seconds >> 17); /* 设置高16位 */
SNVS->LPSRTCLR = (unsigned int)(seconds << 15); /* 设置地16位 */
/* 如果此前RTC是打开的在设置完RTC时间以后需要重新打开RTC */
if (tmp & 0x1)
rtc_enable();
}
/*
* @description : 将秒数转换为时间
* @param - seconds : 要转换的秒数
* @param - datetime: 转换后的日期和时间
* @return : 无
*/
void rtc_convertseconds_to_datetime(unsigned int seconds, struct rtc_datetime *datetime)
{
unsigned int x;
unsigned int secondsRemaining, days;
unsigned short daysInYear;
/* 每个月的天数 */
unsigned char daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
secondsRemaining = seconds; /* 剩余秒数初始化 */
days = secondsRemaining / SECONDS_IN_A_DAY + 1; /* 根据秒数计算天数,加1是当前天数 */
secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY; /*计算天数以后剩余的秒数 */
/* 计算时、分、秒 */
datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
datetime->minute = secondsRemaining / 60;
datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
/* 计算年 */
daysInYear = DAYS_IN_A_YEAR;
datetime->year = YEAR_RANGE_START;
while(days > daysInYear)
{
/* 根据天数计算年 */
days -= daysInYear;
datetime->year++;
/* 处理闰年 */
if (!rtc_isleapyear(datetime->year))
daysInYear = DAYS_IN_A_YEAR;
else /*闰年,天数加一 */
daysInYear = DAYS_IN_A_YEAR + 1;
}
/*根据剩余的天数计算月份 */
if(rtc_isleapyear(datetime->year)) /* 如果是闰年的话2月加一天 */
daysPerMonth[2] = 29;
for(x = 1; x <= 12; x++)
{
if (days <= daysPerMonth[x])
{
datetime->month = x;
break;
}
else
{
days -= daysPerMonth[x];
}
}
datetime->day = days;
}
/*
* @description : 获取RTC当前秒数
* @param : 无
* @return : 当前秒数
*/
unsigned int rtc_getseconds(void)
{
unsigned int seconds = 0;
seconds = (SNVS->LPSRTCMR << 17) | (SNVS->LPSRTCLR >> 15);
return seconds;
}
/*
* @description : 获取当前时间
* @param - datetime: 获取到的时间,日期等参数
* @return : 无
*/
void rtc_getdatetime(struct rtc_datetime *datetime)
{
unsigned int seconds = 0;
seconds = rtc_getseconds();
rtc_convertseconds_to_datetime(seconds, datetime);
}

View File

@@ -0,0 +1,46 @@
#ifndef _BSP_RTC_H
#define _BSP_RTC_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_rtc.c
作者 : 左忠凯
版本 : V1.0
描述 : RTC驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 相关宏定义 */
#define SECONDS_IN_A_DAY (86400) /* 一天86400秒 */
#define SECONDS_IN_A_HOUR (3600) /* 一个小时3600秒 */
#define SECONDS_IN_A_MINUTE (60) /* 一分钟60秒 */
#define DAYS_IN_A_YEAR (365) /* 一年365天 */
#define YEAR_RANGE_START (1970) /* 开始年份1970年 */
#define YEAR_RANGE_END (2099) /* 结束年份2099年 */
/* 时间日期结构体 */
struct rtc_datetime
{
unsigned short year; /* 范围为:1970 ~ 2099 */
unsigned char month; /* 范围为:1 ~ 12 */
unsigned char day; /* 范围为:1 ~ 31 (不同的月,天数不同).*/
unsigned char hour; /* 范围为:0 ~ 23 */
unsigned char minute; /* 范围为:0 ~ 59 */
unsigned char second; /* 范围为:0 ~ 59 */
};
/* 函数声明 */
void rtc_init(void);
void rtc_enable(void);
void rtc_disable(void);
unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime);
unsigned int rtc_getseconds(void);
void rtc_setdatetime(struct rtc_datetime *datetime);
void rtc_getdatetime(struct rtc_datetime *datetime)
;
#endif

View File

@@ -0,0 +1,92 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_spi.c
作者 : 左忠凯
版本 : V1.0
描述 : SPI驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/17 左忠凯创建
***************************************************************/
#include "bsp_spi.h"
#include "bsp_gpio.h"
#include "printf.h"
/*
* @description : 初始化SPI
* @param - base : 要初始化的SPI
* @return : 无
*/
void spi_init(ECSPI_Type *base)
{
/* 1、配置SPI3 */
base->CONREG = 0; /* 先清除控制寄存器 */
/* 配置CONREG寄存器
* bit0 : 1 使能ECSPI
* bit3 : 1 当向TXFIFO写入数据以后立即开启SPI突发。
* bit[7:4] : 0001 SPI通道0主模式根据实际情况选择
* 开发板上的BMP280接在SS0上所以设置通道2为主模式
* bit[19:18]: 00 选中通道0(其实不需要,因为片选信号我们我们自己控制)
* bit[31:20]: 0x7 突发长度为8个bit。
*/
base->CONREG |= (1 << 0) | (1 << 3) | (1 << 4) | (7 << 20); /* 配置CONREG寄存器 */
/*
* ECSPI通道0设置,即设置CONFIGREG寄存器
* bit0: 0 通道0 PHA为0
* bit4: 0 通道0 SCLK高电平有效
* bit8: 0 通道0片选信号 当SMC为1的时候此位无效
* bit12 0 通道0 POL为0
* bit16 0 通道0 数据线空闲时高电平
* bit20: 0 通道0 时钟线空闲时低电平
*/
base->CONFIGREG = 0; /* 设置通道寄存器 */
/*
* ECSPI通道0设置设置采样周期
* bit[14:0] : 0X2000 采样等待周期比如当SPI时钟为10MHz的时候
* 0X2000就等于1/10000 * 0X2000 = 0.8192ms,也就是连续
* 读取数据的时候每次之间间隔0.8ms
* bit15 : 0 采样时钟源为SPI CLK
* bit[21:16]: 0 片选延时可设置为0~63
*/
base->PERIODREG = 0X0000; /* 设置采样周期寄存器 */
/*
* ECSPI的SPI时钟配置SPI的时钟源来源于pll3_sw_clk/8=480/8=60MHz
* 通过设置CONREG寄存器的PER_DIVIDER(bit[11:8])和POST_DIVEDER(bit[15:12])来
* 对SPI时钟源分频获取到我们想要的SPI时钟
* SPI CLK = (SourceCLK / PER_DIVIDER) / (2^POST_DIVEDER)
* 比如我们现在要设置SPI时钟为10MHz那么PER_DIVEIDER和POST_DEIVIDER设置如下
* PER_DIVIDER = 0X5。
* POST_DIVIDER = 0X0。
* SPI CLK = 60000000/(0X9 + 1) = 60000000=6MHz
*/
base->CONREG &= ~((0XF << 12) | (0XF << 8)); /* 清除PER_DIVDER和POST_DIVEDER以前的设置 */
base->CONREG |= (0X9 << 12); /* 设置SPI CLK = 6MHz */
}
/*
* @description : SPI通道0发送/接收一个字节的数据
* @param - base : 要使用的SPI
* @param - txdata : 要发送的数据
* @return : 无
*/
unsigned char spich0_readwrite_byte(ECSPI_Type *base, unsigned char txdata)
{
uint32_t spirxdata = 0;
uint32_t spitxdata = txdata;
/* 选择通道0 */
base->CONREG &= ~(3 << 18);
base->CONREG |= (0 << 18);
while((base->STATREG & (1 << 0)) == 0){} /* 等待发送FIFO为空 */
base->TXDATA = spitxdata;
while((base->STATREG & (1 << 3)) == 0){} /* 等待接收FIFO有数据 */
spirxdata = base->RXDATA;
return spirxdata;
}

View File

@@ -0,0 +1,20 @@
#ifndef _BSP_SPI_H
#define _BSP_SPI_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_spi.h
作者 : 左忠凯
版本 : V1.0
描述 : SPI驱动头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/17 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 函数声明 */
void spi_init(ECSPI_Type *base);
unsigned char spich0_readwrite_byte(ECSPI_Type *base, unsigned char txdata);
#endif

View File

@@ -0,0 +1,239 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_touchscreen.c
作者 : 左忠凯
版本 : V1.0
描述 : 触摸屏驱动文件触摸芯片为FT5426
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/21 左忠凯创建
***************************************************************/
#include "bsp_touchscreen.h"
#include "bsp_i2c.h"
#include "bsp_int.h"
#include "bsp_delay.h"
#include "printf.h"
struct ft5426_dev_struc ft5426_dev;
/*
* @description : 初始化触摸屏其实就是初始化FT5426
* @param : 无
* @return : 无
*/
void touchscreen_init(void)
{
unsigned char reg_value[2];
ft5426_dev.initfalg = FT5426_INIT_NOTFINISHED;
/* 1、初始化IIC2 IO
* I2C2_SCL -> UART5_TXD
* I2C2_SDA -> UART5_RXD
*/
IOMUXC_SetPinMux(IOMUXC_UART5_TX_DATA_I2C2_SCL,1);
IOMUXC_SetPinMux(IOMUXC_UART5_RX_DATA_I2C2_SDA,1);
/* 配置I2C2 IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 1 默认47K上拉
*bit [13]: 1 pull功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 驱动能力为R0/6
*bit [0]: 1 高转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART5_TX_DATA_I2C2_SCL,0x70B0);
IOMUXC_SetPinConfig(IOMUXC_UART5_RX_DATA_I2C2_SDA,0X70B0);
/* 2、初始化触摸屏中断IO和复位IO */
gpio_pin_config_t ctintpin_config;
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO09_GPIO1_IO09,0); /* 复用为GPIO1_IO9 */
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09,0);/* 复用为GPIO5_IO9 */
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09,0xF080);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09,0X10B0);
/* 中断IO初始化 */
ctintpin_config.direction = kGPIO_DigitalInput;
ctintpin_config.interruptMode = kGPIO_IntRisingOrFallingEdge;
gpio_init(GPIO1, 9, &ctintpin_config);
GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn); /* 使能GIC中对应的中断 */
system_register_irqhandler(GPIO1_Combined_0_15_IRQn, (system_irq_handler_t)gpio1_io9_irqhandler, NULL); /* 注册中断服务函数 */
gpio_enableint(GPIO1, 9); /* 使能GPIO1_IO18的中断功能 */
/* 复位IO初始化 */
ctintpin_config.direction=kGPIO_DigitalOutput;
ctintpin_config.interruptMode=kGPIO_NoIntmode;
ctintpin_config.outputLogic=1;
gpio_init(GPIO5, 9, &ctintpin_config);
/* 3、初始化I2C */
i2c_init(I2C2);
/* 4、初始化FT5426 */
gpio_pinwrite(GPIO5, 9, 0); /* 复位FT5426 */
delayms(20);
gpio_pinwrite(GPIO5, 9, 1); /* 停止复位FT5426 */
delayms(20);
ft5426_write_byte(FT5426_ADDR, FT5426_DEVICE_MODE, 0); /* 进入正常模式 */
ft5426_write_byte(FT5426_ADDR, FT5426_IDG_MODE, 1); /* FT5426中断模式 */
ft426_read_len(FT5426_ADDR, FT5426_IDGLIB_VERSION, 2, reg_value);
printf("Touch Frimware Version:%#X\r\n", ((unsigned short)reg_value[0] << 8) + reg_value[1]);
ft5426_dev.initfalg = FT5426_INIT_FINISHED; /* 标记FT5426初始化完成 */
ft5426_dev.intflag = 0;
}
/*
* @description : GPIO1_IO9最终的中断处理函数
* @param : 无
* @return : 无
*/
void gpio1_io9_irqhandler(void)
{
if(ft5426_dev.initfalg == FT5426_INIT_FINISHED)
{
//ft5426_dev.intflag = 1;
ft5426_read_tpcoord();
}
gpio_clearintflags(GPIO1, 9); /* 清除中断标志位 */
}
/*
* @description : 向FT5429写入数据
* @param - addr: 设备地址
* @param - reg : 要写入的寄存器
* @param - data: 要写入的数据
* @return : 操作结果
*/
unsigned char ft5426_write_byte(unsigned char addr,unsigned char reg, unsigned char data)
{
unsigned char status=0;
unsigned char writedata=data;
struct i2c_transfer masterXfer;
/* 配置I2C xfer结构体 */
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Write; /* 写入数据 */
masterXfer.subaddress = reg; /* 要写入的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = &writedata; /* 要写入的数据 */
masterXfer.dataSize = 1; /* 写入数据长度1个字节 */
if(i2c_master_transfer(I2C2, &masterXfer))
status=1;
return status;
}
/*
* @description : 从FT5426读取一个字节的数据
* @param - addr: 设备地址
* @param - reg : 要读取的寄存器
* @return : 读取到的数据。
*/
unsigned char ft5426_read_byte(unsigned char addr,unsigned char reg)
{
unsigned char val=0;
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Read; /* 读取数据 */
masterXfer.subaddress = reg; /* 要读取的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = &val; /* 接收数据缓冲区 */
masterXfer.dataSize = 1; /* 读取数据长度1个字节 */
i2c_master_transfer(I2C2, &masterXfer);
return val;
}
/*
* @description : 从FT5429读取多个字节的数据
* @param - addr: 设备地址
* @param - reg : 要读取的开始寄存器地址
* @param - len : 要读取的数据长度.
* @param - buf : 读取到的数据缓冲区
* @return : 无
*/
void ft426_read_len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf)
{
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr; /* 设备地址 */
masterXfer.direction = kI2C_Read; /* 读取数据 */
masterXfer.subaddress = reg; /* 要读取的寄存器地址 */
masterXfer.subaddressSize = 1; /* 地址长度一个字节 */
masterXfer.data = buf; /* 接收数据缓冲区 */
masterXfer.dataSize = len; /* 读取数据长度1个字节 */
i2c_master_transfer(I2C2, &masterXfer);
}
/*
* @description : 读取当前触摸点个数
* @param : 无
* @return : 无
*/
void ft5426_read_tpnum(void)
{
ft5426_dev.point_num = ft5426_read_byte(FT5426_ADDR, FT5426_TD_STATUS);
}
/*
* @description : 读取当前所有触摸点的坐标
* @param : 无
* @return : 无
*/
void ft5426_read_tpcoord(void)
{
unsigned char i = 0;
unsigned char type = 0;
//unsigned char id = 0;
unsigned char pointbuf[FT5426_XYCOORDREG_NUM];
ft5426_dev.point_num = ft5426_read_byte(FT5426_ADDR, FT5426_TD_STATUS);
/*
* 从寄存器FT5426_TOUCH1_XH开始连续读取30个寄存器的值这30个寄存器
* 保存着5个点的触摸值每个点占用6个寄存器。
*/
ft426_read_len(FT5426_ADDR, FT5426_TOUCH1_XH, FT5426_XYCOORDREG_NUM, pointbuf);
for(i = 0; i < ft5426_dev.point_num ; i++)
{
unsigned char *buf = &pointbuf[i * 6];
/* 以第一个触摸点为例寄存器TOUCH1_XH(地址0X03),各位描述如下:
* bit7:6 Event flag 0:按下 1:释放 2接触 3没有事件
* bit5:4 保留
* bit3:0 X轴触摸点的11~8位。
*/
ft5426_dev.x[i] = ((buf[2] << 8) | buf[3]) & 0x0fff;
ft5426_dev.y[i] = ((buf[0] << 8) | buf[1]) & 0x0fff;
type = buf[0] >> 6; /* 获取触摸类型 */
/* 以第一个触摸点为例寄存器TOUCH1_YH(地址0X05),各位描述如下:
* bit7:4 Touch ID 触摸ID表示是哪个触摸点
* bit3:0 Y轴触摸点的11~8位。
*/
//id = (buf[2] >> 4) & 0x0f;
if(type == FT5426_TOUCH_EVENT_DOWN || type == FT5426_TOUCH_EVENT_ON )/* 按下 */
{
} else { /* 释放 */
}
}
}

View File

@@ -0,0 +1,62 @@
#ifndef _TOUCHSCREEN_H
#define _TOUCHSCREEN_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_touchscreen.c
作者 : 左忠凯
版本 : V1.0
描述 : 触摸屏驱动头文件,触摸芯片为FT5426
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/21 左忠凯创建
***************************************************************/
#include "bsp.h"
#include "bsp_gpio.h"
/* 宏定义 */
#define FT5426_ADDR 0X38 /* FT5426设备地址 */
#define FT5426_DEVICE_MODE 0X00 /* 模式寄存器 */
#define FT5426_IDGLIB_VERSION 0XA1 /* 固件版本寄存器 */
#define FT5426_IDG_MODE 0XA4 /* 模式寄存器 */
#define FT5426_TD_STATUS 0X02 /* 触摸状态寄存器 */
#define FT5426_TOUCH1_XH 0X03 /* 触摸点坐标寄存器,
* 一个触摸点用6个寄存器存储坐标数据
*/
#define FT5426_XYCOORDREG_NUM 30 /* 触摸点坐标寄存器数量 */
#define FT5426_INIT_FINISHED 1 /* 触摸屏初始化完成 */
#define FT5426_INIT_NOTFINISHED 0 /* 触摸屏初始化未完成 */
#define FT5426_TOUCH_EVENT_DOWN 0x00 /* 按下 */
#define FT5426_TOUCH_EVENT_UP 0x01 /* 释放 */
#define FT5426_TOUCH_EVENT_ON 0x02 /* 接触 */
#define FT5426_TOUCH_EVENT_RESERVED 0x03 /* 没有事件 */
/* 触摸屏结构体 */
struct ft5426_dev_struc
{
unsigned char initfalg; /* 触摸屏初始化状态 */
unsigned char intflag; /* 标记中断有没有发生 */
unsigned char point_num; /* 触摸点 */
unsigned short x[5]; /* X轴坐标 */
unsigned short y[5]; /* Y轴坐标 */
};
extern struct ft5426_dev_struc ft5426_dev;
/* 函数声明 */
void touchscreen_init(void);
void gpio1_io9_irqhandler(void);
unsigned char ft5426_write_byte(unsigned char addr,unsigned char reg, unsigned char data);
unsigned char ft5426_read_byte(unsigned char addr,unsigned char reg);
void ft426_read_len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf);
void ft5426_read_tpnum(void);
void ft5426_read_tpcoord(void);
#endif

View File

@@ -0,0 +1,287 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_led.c
作者 : 左忠凯
版本 : V1.0
描述 : 串口驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
#include "bsp_uart.h"
/*
* @description : 初始化串口1,波特率为115200
* @param : 无
* @return : 无
*/
void uart_init(void)
{
/* 1、初始化串口IO */
uart_io_init();
/* 2、初始化UART1 */
uart_disable(UART1); /* 先关闭UART1 */
uart_softreset(UART1); /* 软件复位UART1 */
UART1->
UCR1 = 0; /* 先清除UCR1寄存器 */
/*
* 设置UART的UCR2寄存器设置内容包括字长停止位校验模式关闭RTS硬件流控
* bit14: 1 忽略RTS引脚
* bit8: 0 关闭奇偶校验
* bit6: 0 1位停止位
* bit5: 1 8位数据位
* bit2: 1 打开发送
* bit1: 1 打开接收
*/
UART1->UCR2 |= (1<<14) | (1<<5) | (1<<2) | (1<<1);
/*
* UART1的UCR3寄存器
* bit2: 1 必须设置为1参考IMX6ULL参考手册3642页
*/
UART1->UCR3 |= 1<<2;
/*
* 设置UART的UCR1寄存器关闭自动波特率
* bit14: 0 关闭自动波特率检测,我们自己设置波特率
*/
UART1->UCR1 &= ~(1<<14);
/*
* 设置波特率
* 波特率计算公式:Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1))
* 如果要设置波特率为115200那么可以使用如下参数:
* Ref Freq = 80M 也就是寄存器UFCR的bit9:7=101, 表示1分频
* UBMR = 3124
* UBIR = 71
* 因此波特率= 80000000/(16 * (3124+1)/(71+1))=80000000/(16 * 3125/72) = (80000000*72) / (16*3125) = 115200
*/
UART1->UFCR = 5<<7; //ref freq等于ipg_clk/1=80Mhz
UART1->UBIR = 71;
UART1->UBMR = 3124;
/* 使能串口 */
uart_enable(UART1);
}
/*
* @description : 初始化串口1所使用的IO引脚
* @param : 无
* @return : 无
*/
void uart_io_init(void)
{
/* 1、初始化IO复用
* UART1_RXD -> UART1_TX_DATA
* UART1_TXD -> UART1_RX_DATA
*/
IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0); /* 复用为UART1_TX */
IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0); /* 复用为UART1_RX */
/* 2、配置UART1_TX_DATA、UART1_RX_DATA的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认100K下拉
*bit [13]: 0 keeper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 驱动能力R0/6
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0);
}
/*
* @description : 波特率计算公式,
* 可以用此函数计算出指定串口对应的UFCR
* UBIR和UBMR这三个寄存器的值
* @param - base : 要计算的串口。
* @param - baudrate : 要使用的波特率。
* @param - srcclock_hz :串口时钟源频率单位Hz
* @return : 无
*/
void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz)
{
uint32_t numerator = 0u; //分子
uint32_t denominator = 0U; //分母
uint32_t divisor = 0U;
uint32_t refFreqDiv = 0U;
uint32_t divider = 1U;
uint64_t baudDiff = 0U;
uint64_t tempNumerator = 0U;
uint32_t tempDenominator = 0u;
/* get the approximately maximum divisor */
numerator = srcclock_hz;
denominator = baudrate << 4;
divisor = 1;
while (denominator != 0)
{
divisor = denominator;
denominator = numerator % denominator;
numerator = divisor;
}
numerator = srcclock_hz / divisor;
denominator = (baudrate << 4) / divisor;
/* numerator ranges from 1 ~ 7 * 64k */
/* denominator ranges from 1 ~ 64k */
if ((numerator > (UART_UBIR_INC_MASK * 7)) || (denominator > UART_UBIR_INC_MASK))
{
uint32_t m = (numerator - 1) / (UART_UBIR_INC_MASK * 7) + 1;
uint32_t n = (denominator - 1) / UART_UBIR_INC_MASK + 1;
uint32_t max = m > n ? m : n;
numerator /= max;
denominator /= max;
if (0 == numerator)
{
numerator = 1;
}
if (0 == denominator)
{
denominator = 1;
}
}
divider = (numerator - 1) / UART_UBIR_INC_MASK + 1;
switch (divider)
{
case 1:
refFreqDiv = 0x05;
break;
case 2:
refFreqDiv = 0x04;
break;
case 3:
refFreqDiv = 0x03;
break;
case 4:
refFreqDiv = 0x02;
break;
case 5:
refFreqDiv = 0x01;
break;
case 6:
refFreqDiv = 0x00;
break;
case 7:
refFreqDiv = 0x06;
break;
default:
refFreqDiv = 0x05;
break;
}
/* Compare the difference between baudRate_Bps and calculated baud rate.
* Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).
* baudDiff = (srcClock_Hz/divider)/( 16 * ((numerator / divider)/ denominator).
*/
tempNumerator = srcclock_hz;
tempDenominator = (numerator << 4);
divisor = 1;
/* get the approximately maximum divisor */
while (tempDenominator != 0)
{
divisor = tempDenominator;
tempDenominator = tempNumerator % tempDenominator;
tempNumerator = divisor;
}
tempNumerator = srcclock_hz / divisor;
tempDenominator = (numerator << 4) / divisor;
baudDiff = (tempNumerator * denominator) / tempDenominator;
baudDiff = (baudDiff >= baudrate) ? (baudDiff - baudrate) : (baudrate - baudDiff);
if (baudDiff < (baudrate / 100) * 3)
{
base->UFCR &= ~UART_UFCR_RFDIV_MASK;
base->UFCR |= UART_UFCR_RFDIV(refFreqDiv);
base->UBIR = UART_UBIR_INC(denominator - 1); //要先写UBIR寄存器然后在写UBMR寄存器3592页
base->UBMR = UART_UBMR_MOD(numerator / divider - 1);
//base->ONEMS = UART_ONEMS_ONEMS(srcclock_hz / (1000 * divider));
}
}
/*
* @description : 关闭指定的UART
* @param - base: 要关闭的UART
* @return : 无
*/
void uart_disable(UART_Type *base)
{
base->UCR1 &= ~(1<<0);
}
/*
* @description : 打开指定的UART
* @param - base: 要打开的UART
* @return : 无
*/
void uart_enable(UART_Type *base)
{
base->UCR1 |= (1<<0);
}
/*
* @description : 复位指定的UART
* @param - base: 要复位的UART
* @return : 无
*/
void uart_softreset(UART_Type *base)
{
base->UCR2 &= ~(1<<0); /* UCR2的bit0为0复位UART */
while((base->UCR2 & 0x1) == 0); /* 等待复位完成 */
}
/*
* @description : 发送一个字符
* @param - c : 要发送的字符
* @return : 无
*/
void uart_putc(unsigned char c)
{
while(((UART1->USR2 >> 3) &0X01) == 0);/* 等待上一次发送完成 */
UART1->UTXD = c & 0XFF; /* 发送数据 */
}
/*
* @description : 发送一个字符串
* @param - str : 要发送的字符串
* @return : 无
*/
void uart_puts(char *str)
{
char *p = str;
while(*p)
uart_putc(*p++);
}
/*
* @description : 接收一个字符
* @param : 无
* @return : 接收到的字符
*/
unsigned char uart_getc(void)
{
while((UART1->USR2 & 0x1) == 0);/* 等待接收完成 */
return UART1->URXD; /* 返回接收到的数据 */
}
/*
* @description : 防止编译器报错
* @param : 无
* @return : 无
*/
void raise(int sig_nr)
{
}

View File

@@ -0,0 +1,28 @@
#ifndef _BSP_UART_H
#define _BSP_UART_H
#include "bsp.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_led.c
作者 : 左忠凯
版本 : V1.0
描述 : 串口驱动文件头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
/* 函数声明 */
void uart_init(void);
void uart_io_init(void);
void uart_disable(UART_Type *base);
void uart_enable(UART_Type *base);
void uart_softreset(UART_Type *base);
void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz);
void uart_putc(unsigned char c);
void uart_puts(char *str);
unsigned char uart_getc(void);
void raise(int sig_nr);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
#ifndef __IMX6UL_H
#define __IMX6UL_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp.h
作者 : 左忠凯
版本 : V1.0
描述 : 包含一些常用的头文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
#include "cc.h"
#include "MCIMX6Y2.h"
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "core_ca7.h"
#endif

View File

@@ -0,0 +1,40 @@
#ifndef __CC_H
#define __CC_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : cc.h
作者 : 左忠凯
版本 : V1.0
描述 : 有关变量类型的定义NXP官方SDK的一些移植文件会用到。
其他 : 无
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
/*
* 自定义一些数据类型供库文件使用
*/
#define __I volatile
#define __O volatile
#define __IO volatile
#define ON 1
#define OFF 0
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char s8;
typedef signed short int s16;
typedef signed int s32;
typedef signed long long int s64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
#endif

View File

@@ -0,0 +1,733 @@
#ifndef __CORTEX_CA7_H
#define __CORTEX_CA7_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : core_ca7.h
作者 : 左忠凯
版本 : V1.0
描述 : Cortex-A7内核通用文件。
其他 : 本文件主要实现了对GIC操作函数
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include <stdint.h>
#include <string.h>
#define FORCEDINLINE __attribute__((always_inline))
#define __ASM __asm /* GNU C语言内嵌汇编关键字 */
#define __INLINE inline /* GNU内联关键字 */
#define __STATIC_INLINE static inline
#define __IM volatile const /* 只读 */
#define __OM volatile /* 只写 */
#define __IOM volatile /* 读写 */
#define __STRINGIFY(x) #x
/* C语言实现MCR指令 */
#define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \
__ASM volatile ("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: : "r" (src) )
/* C语言实现MRC指令 */
#define __MRC(coproc, opcode_1, CRn, CRm, opcode_2) \
({ \
uint32_t __dst; \
__ASM volatile ("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: "=r" (__dst) ); \
__dst; \
})
/* 其他一些C语言内嵌汇编 */
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_APSR(uint32_t apsr)
{
__ASM volatile ("MSR apsr, %0" : : "r" (apsr) : "cc");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, cpsr" : "=r" (result) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
{
__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPEXC(void)
{
uint32_t result;
__ASM volatile ("VMRS %0, fpexc" : "=r" (result) );
return result;
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
{
__ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc));
}
/*******************************************************************************
* 一些内核寄存器定义和抽象
定义如下几个内核寄存器:
- CPSR
- CP15
******************************************************************************/
/* CPSR寄存器
* 参考资料ARM Cortex-A(armV7)编程手册V4.0.pdf P46
*/
typedef union
{
struct
{
uint32_t M:5; /*!< bit: 0.. 4 Mode field */
uint32_t T:1; /*!< bit: 5 Thumb execution state bit */
uint32_t F:1; /*!< bit: 6 FIQ mask bit */
uint32_t I:1; /*!< bit: 7 IRQ mask bit */
uint32_t A:1; /*!< bit: 8 Asynchronous abort mask bit */
uint32_t E:1; /*!< bit: 9 Endianness execution state bit */
uint32_t IT1:6; /*!< bit: 10..15 If-Then execution state bits 2-7 */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved0:4; /*!< bit: 20..23 Reserved */
uint32_t J:1; /*!< bit: 24 Jazelle bit */
uint32_t IT0:2; /*!< bit: 25..26 If-Then execution state bits 0-1 */
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 */
} CPSR_Type;
/* CP15的SCTLR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P105
*/
typedef union
{
struct
{
uint32_t M:1; /*!< bit: 0 MMU enable */
uint32_t A:1; /*!< bit: 1 Alignment check enable */
uint32_t C:1; /*!< bit: 2 Cache enable */
uint32_t _reserved0:2; /*!< bit: 3.. 4 Reserved */
uint32_t CP15BEN:1; /*!< bit: 5 CP15 barrier enable */
uint32_t _reserved1:1; /*!< bit: 6 Reserved */
uint32_t B:1; /*!< bit: 7 Endianness model */
uint32_t _reserved2:2; /*!< bit: 8.. 9 Reserved */
uint32_t SW:1; /*!< bit: 10 SWP and SWPB enable */
uint32_t Z:1; /*!< bit: 11 Branch prediction enable */
uint32_t I:1; /*!< bit: 12 Instruction cache enable */
uint32_t V:1; /*!< bit: 13 Vectors bit */
uint32_t RR:1; /*!< bit: 14 Round Robin select */
uint32_t _reserved3:2; /*!< bit:15..16 Reserved */
uint32_t HA:1; /*!< bit: 17 Hardware Access flag enable */
uint32_t _reserved4:1; /*!< bit: 18 Reserved */
uint32_t WXN:1; /*!< bit: 19 Write permission implies XN */
uint32_t UWXN:1; /*!< bit: 20 Unprivileged write permission implies PL1 XN */
uint32_t FI:1; /*!< bit: 21 Fast interrupts configuration enable */
uint32_t U:1; /*!< bit: 22 Alignment model */
uint32_t _reserved5:1; /*!< bit: 23 Reserved */
uint32_t VE:1; /*!< bit: 24 Interrupt Vectors Enable */
uint32_t EE:1; /*!< bit: 25 Exception Endianness */
uint32_t _reserved6:1; /*!< bit: 26 Reserved */
uint32_t NMFI:1; /*!< bit: 27 Non-maskable FIQ (NMFI) support */
uint32_t TRE:1; /*!< bit: 28 TEX remap enable. */
uint32_t AFE:1; /*!< bit: 29 Access flag enable */
uint32_t TE:1; /*!< bit: 30 Thumb Exception enable */
uint32_t _reserved7:1; /*!< bit: 31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} SCTLR_Type;
/* CP15 寄存器SCTLR各个位定义 */
#define SCTLR_TE_Pos 30U /*!< SCTLR: TE Position */
#define SCTLR_TE_Msk (1UL << SCTLR_TE_Pos) /*!< SCTLR: TE Mask */
#define SCTLR_AFE_Pos 29U /*!< SCTLR: AFE Position */
#define SCTLR_AFE_Msk (1UL << SCTLR_AFE_Pos) /*!< SCTLR: AFE Mask */
#define SCTLR_TRE_Pos 28U /*!< SCTLR: TRE Position */
#define SCTLR_TRE_Msk (1UL << SCTLR_TRE_Pos) /*!< SCTLR: TRE Mask */
#define SCTLR_NMFI_Pos 27U /*!< SCTLR: NMFI Position */
#define SCTLR_NMFI_Msk (1UL << SCTLR_NMFI_Pos) /*!< SCTLR: NMFI Mask */
#define SCTLR_EE_Pos 25U /*!< SCTLR: EE Position */
#define SCTLR_EE_Msk (1UL << SCTLR_EE_Pos) /*!< SCTLR: EE Mask */
#define SCTLR_VE_Pos 24U /*!< SCTLR: VE Position */
#define SCTLR_VE_Msk (1UL << SCTLR_VE_Pos) /*!< SCTLR: VE Mask */
#define SCTLR_U_Pos 22U /*!< SCTLR: U Position */
#define SCTLR_U_Msk (1UL << SCTLR_U_Pos) /*!< SCTLR: U Mask */
#define SCTLR_FI_Pos 21U /*!< SCTLR: FI Position */
#define SCTLR_FI_Msk (1UL << SCTLR_FI_Pos) /*!< SCTLR: FI Mask */
#define SCTLR_UWXN_Pos 20U /*!< SCTLR: UWXN Position */
#define SCTLR_UWXN_Msk (1UL << SCTLR_UWXN_Pos) /*!< SCTLR: UWXN Mask */
#define SCTLR_WXN_Pos 19U /*!< SCTLR: WXN Position */
#define SCTLR_WXN_Msk (1UL << SCTLR_WXN_Pos) /*!< SCTLR: WXN Mask */
#define SCTLR_HA_Pos 17U /*!< SCTLR: HA Position */
#define SCTLR_HA_Msk (1UL << SCTLR_HA_Pos) /*!< SCTLR: HA Mask */
#define SCTLR_RR_Pos 14U /*!< SCTLR: RR Position */
#define SCTLR_RR_Msk (1UL << SCTLR_RR_Pos) /*!< SCTLR: RR Mask */
#define SCTLR_V_Pos 13U /*!< SCTLR: V Position */
#define SCTLR_V_Msk (1UL << SCTLR_V_Pos) /*!< SCTLR: V Mask */
#define SCTLR_I_Pos 12U /*!< SCTLR: I Position */
#define SCTLR_I_Msk (1UL << SCTLR_I_Pos) /*!< SCTLR: I Mask */
#define SCTLR_Z_Pos 11U /*!< SCTLR: Z Position */
#define SCTLR_Z_Msk (1UL << SCTLR_Z_Pos) /*!< SCTLR: Z Mask */
#define SCTLR_SW_Pos 10U /*!< SCTLR: SW Position */
#define SCTLR_SW_Msk (1UL << SCTLR_SW_Pos) /*!< SCTLR: SW Mask */
#define SCTLR_B_Pos 7U /*!< SCTLR: B Position */
#define SCTLR_B_Msk (1UL << SCTLR_B_Pos) /*!< SCTLR: B Mask */
#define SCTLR_CP15BEN_Pos 5U /*!< SCTLR: CP15BEN Position */
#define SCTLR_CP15BEN_Msk (1UL << SCTLR_CP15BEN_Pos) /*!< SCTLR: CP15BEN Mask */
#define SCTLR_C_Pos 2U /*!< SCTLR: C Position */
#define SCTLR_C_Msk (1UL << SCTLR_C_Pos) /*!< SCTLR: C Mask */
#define SCTLR_A_Pos 1U /*!< SCTLR: A Position */
#define SCTLR_A_Msk (1UL << SCTLR_A_Pos) /*!< SCTLR: A Mask */
#define SCTLR_M_Pos 0U /*!< SCTLR: M Position */
#define SCTLR_M_Msk (1UL << SCTLR_M_Pos) /*!< SCTLR: M Mask */
/* CP15的ACTLR寄存器
* 参考资料:Cortex-A7 Technical ReferenceManua.pdf P113
*/
typedef union
{
struct
{
uint32_t _reserved0:6; /*!< bit: 0.. 5 Reserved */
uint32_t SMP:1; /*!< bit: 6 Enables coherent requests to the processor */
uint32_t _reserved1:3; /*!< bit: 7.. 9 Reserved */
uint32_t DODMBS:1; /*!< bit: 10 Disable optimized data memory barrier behavior */
uint32_t L2RADIS:1; /*!< bit: 11 L2 Data Cache read-allocate mode disable */
uint32_t L1RADIS:1; /*!< bit: 12 L1 Data Cache read-allocate mode disable */
uint32_t L1PCTL:2; /*!< bit:13..14 L1 Data prefetch control */
uint32_t DDVM:1; /*!< bit: 15 Disable Distributed Virtual Memory (DVM) transactions */
uint32_t _reserved3:12; /*!< bit:16..27 Reserved */
uint32_t DDI:1; /*!< bit: 28 Disable dual issue */
uint32_t _reserved7:3; /*!< bit:29..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} ACTLR_Type;
#define ACTLR_DDI_Pos 28U /*!< ACTLR: DDI Position */
#define ACTLR_DDI_Msk (1UL << ACTLR_DDI_Pos) /*!< ACTLR: DDI Mask */
#define ACTLR_DDVM_Pos 15U /*!< ACTLR: DDVM Position */
#define ACTLR_DDVM_Msk (1UL << ACTLR_DDVM_Pos) /*!< ACTLR: DDVM Mask */
#define ACTLR_L1PCTL_Pos 13U /*!< ACTLR: L1PCTL Position */
#define ACTLR_L1PCTL_Msk (3UL << ACTLR_L1PCTL_Pos) /*!< ACTLR: L1PCTL Mask */
#define ACTLR_L1RADIS_Pos 12U /*!< ACTLR: L1RADIS Position */
#define ACTLR_L1RADIS_Msk (1UL << ACTLR_L1RADIS_Pos) /*!< ACTLR: L1RADIS Mask */
#define ACTLR_L2RADIS_Pos 11U /*!< ACTLR: L2RADIS Position */
#define ACTLR_L2RADIS_Msk (1UL << ACTLR_L2RADIS_Pos) /*!< ACTLR: L2RADIS Mask */
#define ACTLR_DODMBS_Pos 10U /*!< ACTLR: DODMBS Position */
#define ACTLR_DODMBS_Msk (1UL << ACTLR_DODMBS_Pos) /*!< ACTLR: DODMBS Mask */
#define ACTLR_SMP_Pos 6U /*!< ACTLR: SMP Position */
#define ACTLR_SMP_Msk (1UL << ACTLR_SMP_Pos) /*!< ACTLR: SMP Mask */
/* CP15的CPACR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P115
*/
typedef union
{
struct
{
uint32_t _reserved0:20; /*!< bit: 0..19 Reserved */
uint32_t cp10:2; /*!< bit:20..21 Access rights for coprocessor 10 */
uint32_t cp11:2; /*!< bit:22..23 Access rights for coprocessor 11 */
uint32_t _reserved1:6; /*!< bit:24..29 Reserved */
uint32_t D32DIS:1; /*!< bit: 30 Disable use of registers D16-D31 of the VFP register file */
uint32_t ASEDIS:1; /*!< bit: 31 Disable Advanced SIMD Functionality */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CPACR_Type;
#define CPACR_ASEDIS_Pos 31U /*!< CPACR: ASEDIS Position */
#define CPACR_ASEDIS_Msk (1UL << CPACR_ASEDIS_Pos) /*!< CPACR: ASEDIS Mask */
#define CPACR_D32DIS_Pos 30U /*!< CPACR: D32DIS Position */
#define CPACR_D32DIS_Msk (1UL << CPACR_D32DIS_Pos) /*!< CPACR: D32DIS Mask */
#define CPACR_cp11_Pos 22U /*!< CPACR: cp11 Position */
#define CPACR_cp11_Msk (3UL << CPACR_cp11_Pos) /*!< CPACR: cp11 Mask */
#define CPACR_cp10_Pos 20U /*!< CPACR: cp10 Position */
#define CPACR_cp10_Msk (3UL << CPACR_cp10_Pos) /*!< CPACR: cp10 Mask */
/* CP15的DFSR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P128
*/
typedef union
{
struct
{
uint32_t FS0:4; /*!< bit: 0.. 3 Fault Status bits bit 0-3 */
uint32_t Domain:4; /*!< bit: 4.. 7 Fault on which domain */
uint32_t _reserved0:2; /*!< bit: 8.. 9 Reserved */
uint32_t FS1:1; /*!< bit: 10 Fault Status bits bit 4 */
uint32_t WnR:1; /*!< bit: 11 Write not Read bit */
uint32_t ExT:1; /*!< bit: 12 External abort type */
uint32_t CM:1; /*!< bit: 13 Cache maintenance fault */
uint32_t _reserved1:18; /*!< bit:14..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} DFSR_Type;
#define DFSR_CM_Pos 13U /*!< DFSR: CM Position */
#define DFSR_CM_Msk (1UL << DFSR_CM_Pos) /*!< DFSR: CM Mask */
#define DFSR_Ext_Pos 12U /*!< DFSR: Ext Position */
#define DFSR_Ext_Msk (1UL << DFSR_Ext_Pos) /*!< DFSR: Ext Mask */
#define DFSR_WnR_Pos 11U /*!< DFSR: WnR Position */
#define DFSR_WnR_Msk (1UL << DFSR_WnR_Pos) /*!< DFSR: WnR Mask */
#define DFSR_FS1_Pos 10U /*!< DFSR: FS1 Position */
#define DFSR_FS1_Msk (1UL << DFSR_FS1_Pos) /*!< DFSR: FS1 Mask */
#define DFSR_Domain_Pos 4U /*!< DFSR: Domain Position */
#define DFSR_Domain_Msk (0xFUL << DFSR_Domain_Pos) /*!< DFSR: Domain Mask */
#define DFSR_FS0_Pos 0U /*!< DFSR: FS0 Position */
#define DFSR_FS0_Msk (0xFUL << DFSR_FS0_Pos) /*!< DFSR: FS0 Mask */
/* CP15的IFSR寄存器
* 参考资料Cortex-A7 Technical ReferenceManua.pdf P131
*/
typedef union
{
struct
{
uint32_t FS0:4; /*!< bit: 0.. 3 Fault Status bits bit 0-3 */
uint32_t _reserved0:6; /*!< bit: 4.. 9 Reserved */
uint32_t FS1:1; /*!< bit: 10 Fault Status bits bit 4 */
uint32_t _reserved1:1; /*!< bit: 11 Reserved */
uint32_t ExT:1; /*!< bit: 12 External abort type */
uint32_t _reserved2:19; /*!< bit:13..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IFSR_Type;
#define IFSR_ExT_Pos 12U /*!< IFSR: ExT Position */
#define IFSR_ExT_Msk (1UL << IFSR_ExT_Pos) /*!< IFSR: ExT Mask */
#define IFSR_FS1_Pos 10U /*!< IFSR: FS1 Position */
#define IFSR_FS1_Msk (1UL << IFSR_FS1_Pos) /*!< IFSR: FS1 Mask */
#define IFSR_FS0_Pos 0U /*!< IFSR: FS0 Position */
#define IFSR_FS0_Msk (0xFUL << IFSR_FS0_Pos) /*!< IFSR: FS0 Mask */
/* CP15的ISR寄存器
* 参考资料ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf P1640
*/
typedef union
{
struct
{
uint32_t _reserved0:6; /*!< bit: 0.. 5 Reserved */
uint32_t F:1; /*!< bit: 6 FIQ pending bit */
uint32_t I:1; /*!< bit: 7 IRQ pending bit */
uint32_t A:1; /*!< bit: 8 External abort pending bit */
uint32_t _reserved1:23; /*!< bit:14..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} ISR_Type;
#define ISR_A_Pos 13U /*!< ISR: A Position */
#define ISR_A_Msk (1UL << ISR_A_Pos) /*!< ISR: A Mask */
#define ISR_I_Pos 12U /*!< ISR: I Position */
#define ISR_I_Msk (1UL << ISR_I_Pos) /*!< ISR: I Mask */
#define ISR_F_Pos 11U /*!< ISR: F Position */
#define ISR_F_Msk (1UL << ISR_F_Pos) /*!< ISR: F Mask */
/* Mask and shift a bit field value for use in a register bit range. */
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
/* Mask and shift a register value to extract a bit filed value. */
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
/*******************************************************************************
* CP15 访问函数
******************************************************************************/
FORCEDINLINE __STATIC_INLINE uint32_t __get_SCTLR(void)
{
return __MRC(15, 0, 1, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{
__MCR(15, 0, sctlr, 1, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_ACTLR(void)
{
return __MRC(15, 0, 1, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_ACTLR(uint32_t actlr)
{
__MCR(15, 0, actlr, 1, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_CPACR(void)
{
return __MRC(15, 0, 1, 0, 2);
}
FORCEDINLINE __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{
__MCR(15, 0, cpacr, 1, 0, 2);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_TTBR0(void)
{
return __MRC(15, 0, 2, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_TTBR0(uint32_t ttbr0)
{
__MCR(15, 0, ttbr0, 2, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_TTBR1(void)
{
return __MRC(15, 0, 2, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_TTBR1(uint32_t ttbr1)
{
__MCR(15, 0, ttbr1, 2, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_TTBCR(void)
{
return __MRC(15, 0, 2, 0, 2);
}
FORCEDINLINE __STATIC_INLINE void __set_TTBCR(uint32_t ttbcr)
{
__MCR(15, 0, ttbcr, 2, 0, 2);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_DACR(void)
{
return __MRC(15, 0, 3, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_DACR(uint32_t dacr)
{
__MCR(15, 0, dacr, 3, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_DFSR(void)
{
return __MRC(15, 0, 5, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_DFSR(uint32_t dfsr)
{
__MCR(15, 0, dfsr, 5, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_IFSR(void)
{
return __MRC(15, 0, 5, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_IFSR(uint32_t ifsr)
{
__MCR(15, 0, ifsr, 5, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_DFAR(void)
{
return __MRC(15, 0, 6, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_DFAR(uint32_t dfar)
{
__MCR(15, 0, dfar, 6, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_IFAR(void)
{
return __MRC(15, 0, 6, 0, 2);
}
FORCEDINLINE __STATIC_INLINE void __set_IFAR(uint32_t ifar)
{
__MCR(15, 0, ifar, 6, 0, 2);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_VBAR(void)
{
return __MRC(15, 0, 12, 0, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_VBAR(uint32_t vbar)
{
__MCR(15, 0, vbar, 12, 0, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_ISR(void)
{
return __MRC(15, 0, 12, 1, 0);
}
FORCEDINLINE __STATIC_INLINE void __set_ISR(uint32_t isr)
{
__MCR(15, 0, isr, 12, 1, 0);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_CONTEXTIDR(void)
{
return __MRC(15, 0, 13, 0, 1);
}
FORCEDINLINE __STATIC_INLINE void __set_CONTEXTIDR(uint32_t contextidr)
{
__MCR(15, 0, contextidr, 13, 0, 1);
}
FORCEDINLINE __STATIC_INLINE uint32_t __get_CBAR(void)
{
return __MRC(15, 4, 15, 0, 0);
}
/*******************************************************************************
* GIC相关内容
*有关GIC的内容参考ARM Generic Interrupt Controller(ARM GIC控制器)V2.0.pdf
******************************************************************************/
/*
* GIC寄存器描述结构体
* GIC分为分发器端和CPU接口端
*/
typedef struct
{
uint32_t RESERVED0[1024];
__IOM uint32_t D_CTLR; /*!< Offset: 0x1000 (R/W) Distributor Control Register */
__IM uint32_t D_TYPER; /*!< Offset: 0x1004 (R/ ) Interrupt Controller Type Register */
__IM uint32_t D_IIDR; /*!< Offset: 0x1008 (R/ ) Distributor Implementer Identification Register */
uint32_t RESERVED1[29];
__IOM uint32_t D_IGROUPR[16]; /*!< Offset: 0x1080 - 0x0BC (R/W) Interrupt Group Registers */
uint32_t RESERVED2[16];
__IOM uint32_t D_ISENABLER[16]; /*!< Offset: 0x1100 - 0x13C (R/W) Interrupt Set-Enable Registers */
uint32_t RESERVED3[16];
__IOM uint32_t D_ICENABLER[16]; /*!< Offset: 0x1180 - 0x1BC (R/W) Interrupt Clear-Enable Registers */
uint32_t RESERVED4[16];
__IOM uint32_t D_ISPENDR[16]; /*!< Offset: 0x1200 - 0x23C (R/W) Interrupt Set-Pending Registers */
uint32_t RESERVED5[16];
__IOM uint32_t D_ICPENDR[16]; /*!< Offset: 0x1280 - 0x2BC (R/W) Interrupt Clear-Pending Registers */
uint32_t RESERVED6[16];
__IOM uint32_t D_ISACTIVER[16]; /*!< Offset: 0x1300 - 0x33C (R/W) Interrupt Set-Active Registers */
uint32_t RESERVED7[16];
__IOM uint32_t D_ICACTIVER[16]; /*!< Offset: 0x1380 - 0x3BC (R/W) Interrupt Clear-Active Registers */
uint32_t RESERVED8[16];
__IOM uint8_t D_IPRIORITYR[512]; /*!< Offset: 0x1400 - 0x5FC (R/W) Interrupt Priority Registers */
uint32_t RESERVED9[128];
__IOM uint8_t D_ITARGETSR[512]; /*!< Offset: 0x1800 - 0x9FC (R/W) Interrupt Targets Registers */
uint32_t RESERVED10[128];
__IOM uint32_t D_ICFGR[32]; /*!< Offset: 0x1C00 - 0xC7C (R/W) Interrupt configuration registers */
uint32_t RESERVED11[32];
__IM uint32_t D_PPISR; /*!< Offset: 0x1D00 (R/ ) Private Peripheral Interrupt Status Register */
__IM uint32_t D_SPISR[15]; /*!< Offset: 0x1D04 - 0xD3C (R/ ) Shared Peripheral Interrupt Status Registers */
uint32_t RESERVED12[112];
__OM uint32_t D_SGIR; /*!< Offset: 0x1F00 ( /W) Software Generated Interrupt Register */
uint32_t RESERVED13[3];
__IOM uint8_t D_CPENDSGIR[16]; /*!< Offset: 0x1F10 - 0xF1C (R/W) SGI Clear-Pending Registers */
__IOM uint8_t D_SPENDSGIR[16]; /*!< Offset: 0x1F20 - 0xF2C (R/W) SGI Set-Pending Registers */
uint32_t RESERVED14[40];
__IM uint32_t D_PIDR4; /*!< Offset: 0x1FD0 (R/ ) Peripheral ID4 Register */
__IM uint32_t D_PIDR5; /*!< Offset: 0x1FD4 (R/ ) Peripheral ID5 Register */
__IM uint32_t D_PIDR6; /*!< Offset: 0x1FD8 (R/ ) Peripheral ID6 Register */
__IM uint32_t D_PIDR7; /*!< Offset: 0x1FDC (R/ ) Peripheral ID7 Register */
__IM uint32_t D_PIDR0; /*!< Offset: 0x1FE0 (R/ ) Peripheral ID0 Register */
__IM uint32_t D_PIDR1; /*!< Offset: 0x1FE4 (R/ ) Peripheral ID1 Register */
__IM uint32_t D_PIDR2; /*!< Offset: 0x1FE8 (R/ ) Peripheral ID2 Register */
__IM uint32_t D_PIDR3; /*!< Offset: 0x1FEC (R/ ) Peripheral ID3 Register */
__IM uint32_t D_CIDR0; /*!< Offset: 0x1FF0 (R/ ) Component ID0 Register */
__IM uint32_t D_CIDR1; /*!< Offset: 0x1FF4 (R/ ) Component ID1 Register */
__IM uint32_t D_CIDR2; /*!< Offset: 0x1FF8 (R/ ) Component ID2 Register */
__IM uint32_t D_CIDR3; /*!< Offset: 0x1FFC (R/ ) Component ID3 Register */
__IOM uint32_t C_CTLR; /*!< Offset: 0x2000 (R/W) CPU Interface Control Register */
__IOM uint32_t C_PMR; /*!< Offset: 0x2004 (R/W) Interrupt Priority Mask Register */
__IOM uint32_t C_BPR; /*!< Offset: 0x2008 (R/W) Binary Point Register */
__IM uint32_t C_IAR; /*!< Offset: 0x200C (R/ ) Interrupt Acknowledge Register */
__OM uint32_t C_EOIR; /*!< Offset: 0x2010 ( /W) End Of Interrupt Register */
__IM uint32_t C_RPR; /*!< Offset: 0x2014 (R/ ) Running Priority Register */
__IM uint32_t C_HPPIR; /*!< Offset: 0x2018 (R/ ) Highest Priority Pending Interrupt Register */
__IOM uint32_t C_ABPR; /*!< Offset: 0x201C (R/W) Aliased Binary Point Register */
__IM uint32_t C_AIAR; /*!< Offset: 0x2020 (R/ ) Aliased Interrupt Acknowledge Register */
__OM uint32_t C_AEOIR; /*!< Offset: 0x2024 ( /W) Aliased End Of Interrupt Register */
__IM uint32_t C_AHPPIR; /*!< Offset: 0x2028 (R/ ) Aliased Highest Priority Pending Interrupt Register */
uint32_t RESERVED15[41];
__IOM uint32_t C_APR0; /*!< Offset: 0x20D0 (R/W) Active Priority Register */
uint32_t RESERVED16[3];
__IOM uint32_t C_NSAPR0; /*!< Offset: 0x20E0 (R/W) Non-secure Active Priority Register */
uint32_t RESERVED17[6];
__IM uint32_t C_IIDR; /*!< Offset: 0x20FC (R/ ) CPU Interface Identification Register */
uint32_t RESERVED18[960];
__OM uint32_t C_DIR; /*!< Offset: 0x3000 ( /W) Deactivate Interrupt Register */
} GIC_Type;
/*
* GIC初始化
* 为了简单使用GIC的group0
*/
FORCEDINLINE __STATIC_INLINE void GIC_Init(void)
{
uint32_t i;
uint32_t irqRegs;
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
irqRegs = (gic->D_TYPER & 0x1FUL) + 1;
/* On POR, all SPI is in group 0, level-sensitive and using 1-N model */
/* Disable all PPI, SGI and SPI */
for (i = 0; i < irqRegs; i++)
gic->D_ICENABLER[i] = 0xFFFFFFFFUL;
/* Make all interrupts have higher priority */
gic->C_PMR = (0xFFUL << (8 - __GIC_PRIO_BITS)) & 0xFFUL;
/* No subpriority, all priority level allows preemption */
gic->C_BPR = 7 - __GIC_PRIO_BITS;
/* Enable group0 distribution */
gic->D_CTLR = 1UL;
/* Enable group0 signaling */
gic->C_CTLR = 1UL;
}
/*
* 使能指定的中断
*/
FORCEDINLINE __STATIC_INLINE void GIC_EnableIRQ(IRQn_Type IRQn)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->D_ISENABLER[((uint32_t)(int32_t)IRQn) >> 5] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/*
* 关闭指定的中断
*/
FORCEDINLINE __STATIC_INLINE void GIC_DisableIRQ(IRQn_Type IRQn)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->D_ICENABLER[((uint32_t)(int32_t)IRQn) >> 5] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/*
* 返回中断号
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_AcknowledgeIRQ(void)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return gic->C_IAR & 0x1FFFUL;
}
/*
* 向EOIR写入发送中断的中断号来释放中断
*/
FORCEDINLINE __STATIC_INLINE void GIC_DeactivateIRQ(uint32_t value)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->C_EOIR = value;
}
/*
* 获取运行优先级
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_GetRunningPriority(void)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return gic->C_RPR & 0xFFUL;
}
/*
* 设置组优先级
*/
FORCEDINLINE __STATIC_INLINE void GIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->C_BPR = PriorityGroup & 0x7UL;
}
/*
* 获取组优先级
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_GetPriorityGrouping(void)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return gic->C_BPR & 0x7UL;
}
/*
* 设置优先级
*/
FORCEDINLINE __STATIC_INLINE void GIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
gic->D_IPRIORITYR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8UL - __GIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
/*
* 获取优先级
*/
FORCEDINLINE __STATIC_INLINE uint32_t GIC_GetPriority(IRQn_Type IRQn)
{
GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
return(((uint32_t)gic->D_IPRIORITYR[((uint32_t)(int32_t)IRQn)] >> (8UL - __GIC_PRIO_BITS)));
}
#endif

View File

@@ -0,0 +1,124 @@
/**************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : fsl_common.h
作者 : 左忠凯修改NXP官方SDK
版本 : V1.0
描述 : NXP官方SDK的通用关宏定义文档
其他 : NXP官方SDK的通用宏定义文档默认基于IAR的
由左忠凯移植到Liux下。
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/4 左忠凯移植
**************************************************************/
#ifndef _FSL_COMMON_H_
#define _FSL_COMMON_H_
#include "cc.h" /* cc.h为自行添加的文件 */
/*!
* @addtogroup ksdk_common
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/* Debug console type definition. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console base on LPC_USART. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_MICFIL = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */
};
/*! @brief Generic status return codes. */
enum _generic_status
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
#endif /* _FSL_COMMON_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
#include "tos_k.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_uart.h"
#include "bsp_exit.h"
#include "bsp_epittimer.h"
void task1_entry(void *arg)
{
while (1) {
printf("task1\r\n");
tos_task_delay(2000);
}
}
void task2_entry(void *arg)
{
while (1) {
printf("task2\r\n");
tos_task_delay(3000);
}
}
k_task_t task1;
k_stack_t task1_stack[512];
k_task_t task2;
k_stack_t task2_stack[512];
int main(void)
{
uart_init();
led_init();
beep_init();
key_init();
tos_knl_init();
tos_task_create(&task1, "task1", task1_entry, NULL,
4,
task1_stack, sizeof(task1_stack),
0);
tos_task_create(&task2, "task2", task2_entry, NULL,
4,
task2_stack, sizeof(task2_stack),
0);
tos_knl_start();
return 0;
}

View File

@@ -0,0 +1,49 @@
/*
* NOTE! This ctype does not handle EOF like the standard C
* library is required to.
*/
#define _U 0x01 /* upper */
#define _L 0x02 /* lower */
#define _D 0x04 /* digit */
#define _C 0x08 /* cntrl */
#define _P 0x10 /* punct */
#define _S 0x20 /* white space (space/lf/tab) */
#define _X 0x40 /* hex digit */
#define _SP 0x80 /* hard space (0x20) */
extern unsigned char _ctype[];
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
#define isdigit(c) ((__ismask(c)&(_D)) != 0)
#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
#define islower(c) ((__ismask(c)&(_L)) != 0)
#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
#define ispunct(c) ((__ismask(c)&(_P)) != 0)
#define isspace(c) ((__ismask(c)&(_S)) != 0)
#define isupper(c) ((__ismask(c)&(_U)) != 0)
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)
static inline unsigned char __tolower(unsigned char c)
{
if (isupper(c))
c -= 'A'-'a';
return c;
}
static inline unsigned char __toupper(unsigned char c)
{
if (islower(c))
c -= 'a'-'A';
return c;
}
#define tolower(c) __tolower(c)
#define toupper(c) __toupper(c)

View File

@@ -0,0 +1,35 @@
#ifndef __ASM_ARM_DIV64
#define __ASM_ARM_DIV64
//#include <asm/system.h>
/*
* The semantics of do_div() are:
*
* uint32_t do_div(uint64_t *n, uint32_t base)
* {
* uint32_t remainder = *n % base;
* *n = *n / base;
* return remainder;
* }
*
* In other words, a 64-bit dividend with a 32-bit divisor producing
* a 64-bit result and a 32-bit remainder. To accomplish this optimally
* we call a special __do_div64 helper with completely non standard
* calling convention for arguments and results (beware).
*/
extern unsigned int __div64_32(unsigned long long *dividend, unsigned int divisor);
# define do_div(n,base) ({ \
unsigned int __base = (base); \
unsigned int __rem; \
(void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
if (((n) >> 32) == 0) { \
__rem = (unsigned int)(n) % __base; \
(n) = (unsigned int)(n) / __base; \
} else \
__rem = __div64_32(&(n), __base); \
__rem; \
})
#endif

View File

@@ -0,0 +1,25 @@
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
/* I Molton 29/07/01 */
#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
#ifdef __ARMEB__
struct DIstruct {SItype high, low;};
#else
struct DIstruct {SItype low, high;};
#endif
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;

View File

@@ -0,0 +1,6 @@
#define INT_MAX ((int)(~0U>>1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL>>1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)

View File

@@ -0,0 +1,26 @@
#ifndef _STDIO_H
#define _STDIO_H
#include "types.h"
#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif /* _VALIST */
extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
extern int snprintf(char * buf, size_t size, const char *fmt, ...);
extern int vsprintf(char *buf, const char *fmt, va_list args);
extern int sprintf(char * buf, const char *fmt, ...);
extern int vsscanf(const char * buf, const char * fmt, va_list args);
extern int sscanf(const char * buf, const char * fmt, ...);
extern void putc(unsigned char c);
extern unsigned char getc(void);
int printf(const char *fmt, ...);
int scanf(const char * fmt, ...);
#endif /* _STDIO_H */

View File

@@ -0,0 +1,78 @@
/* We don't want strings.h stuff being user by user stuff by accident */
//#include <linux/types.h> /* for size_t */
//#include <linux/stddef.h> /* for NULL */
#include "types.h"
extern char * ___strtok;
extern char * strpbrk(const char *,const char *);
extern char * strtok(char *,const char *);
extern char * strsep(char **,const char *);
extern size_t strspn(const char *,const char *);
/*
* Include machine specific inline routines
*/
//#include <asm/string.h>
#ifndef __HAVE_ARCH_STRCPY
extern char * strcpy(char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRNCPY
extern char * strncpy(char *,const char *, size_t);
#endif
#ifndef __HAVE_ARCH_STRCAT
extern char * strcat(char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNCAT
extern char * strncat(char *, const char *, size_t);
#endif
#ifndef __HAVE_ARCH_STRCMP
extern int strcmp(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRNCMP
extern int strncmp(const char *,const char *,size_t);
#endif
#ifndef __HAVE_ARCH_STRNICMP
extern int strnicmp(const char *, const char *, size_t);
#endif
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRRCHR
extern char * strrchr(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRSTR
extern char * strstr(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRLEN
extern size_t strlen(const char *);
#endif
#ifndef __HAVE_ARCH_STRNLEN
extern size_t strnlen(const char *,size_t);
#endif
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,size_t);
#endif
#ifndef __HAVE_ARCH_MEMCPY
extern void * memcpy(void *,const void *,size_t);
#endif
#ifndef __HAVE_ARCH_MEMMOVE
extern void * memmove(void *,const void *,size_t);
#endif
#ifndef __HAVE_ARCH_MEMSCAN
extern void * memscan(void *,int,size_t);
#endif
#ifndef __HAVE_ARCH_MEMCMP
extern int memcmp(const void *,const void *,size_t);
#endif
#ifndef __HAVE_ARCH_MEMCHR
extern void * memchr(const void *,int,size_t);
#endif

View File

@@ -0,0 +1,388 @@
#ifndef __ASM_ARM_SYSTEM_H
#define __ASM_ARM_SYSTEM_H
#ifdef __KERNEL__
#include <linux/config.h>
#define CPU_ARCH_UNKNOWN 0
#define CPU_ARCH_ARMv3 1
#define CPU_ARCH_ARMv4 2
#define CPU_ARCH_ARMv4T 3
#define CPU_ARCH_ARMv5 4
#define CPU_ARCH_ARMv5T 5
#define CPU_ARCH_ARMv5TE 6
#define CPU_ARCH_ARMv5TEJ 7
#define CPU_ARCH_ARMv6 8
/*
* CR1 bits (CP#15 CR1)
*/
#define CR_M (1 << 0) /* MMU enable */
#define CR_A (1 << 1) /* Alignment abort enable */
#define CR_C (1 << 2) /* Dcache enable */
#define CR_W (1 << 3) /* Write buffer enable */
#define CR_P (1 << 4) /* 32-bit exception handler */
#define CR_D (1 << 5) /* 32-bit data address range */
#define CR_L (1 << 6) /* Implementation defined */
#define CR_B (1 << 7) /* Big endian */
#define CR_S (1 << 8) /* System MMU protection */
#define CR_R (1 << 9) /* ROM MMU protection */
#define CR_F (1 << 10) /* Implementation defined */
#define CR_Z (1 << 11) /* Implementation defined */
#define CR_I (1 << 12) /* Icache enable */
#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
#define CR_RR (1 << 14) /* Round Robin cache replacement */
#define CR_L4 (1 << 15) /* LDR pc can set T bit */
#define CR_DT (1 << 16)
#define CR_IT (1 << 18)
#define CR_ST (1 << 19)
#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */
#define CR_U (1 << 22) /* Unaligned access operation */
#define CR_XP (1 << 23) /* Extended page tables */
#define CR_VE (1 << 24) /* Vectored interrupts */
#define CPUID_ID 0
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
#define CPUID_TLBTYPE 3
#define read_cpuid(reg) \
({ \
unsigned int __val; \
asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \
: "=r" (__val) \
: \
: "cc"); \
__val; \
})
/*
* This is used to ensure the compiler did actually allocate the register we
* asked it for some inline assembly sequences. Apparently we can't trust
* the compiler from one version to another so a bit of paranoia won't hurt.
* This string is meant to be concatenated with the inline asm string and
* will cause compilation to stop on mismatch.
* (for details, see gcc PR 15089)
*/
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
#ifndef __ASSEMBLY__
#include <linux/linkage.h>
struct thread_info;
struct task_struct;
/* information about the system we're running on */
extern unsigned int system_rev;
extern unsigned int system_serial_low;
extern unsigned int system_serial_high;
extern unsigned int mem_fclk_21285;
struct pt_regs;
void die(const char *msg, struct pt_regs *regs, int err)
__attribute__((noreturn));
void die_if_kernel(const char *str, struct pt_regs *regs, int err);
void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
struct pt_regs *),
int sig, const char *name);
#include <asm/proc-fns.h>
#define xchg(ptr,x) \
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr) (xchg((ptr),1))
extern asmlinkage void __backtrace(void);
extern int cpu_architecture(void);
#define set_cr(x) \
__asm__ __volatile__( \
"mcr p15, 0, %0, c1, c0, 0 @ set CR" \
: : "r" (x) : "cc")
#define get_cr() \
({ \
unsigned int __val; \
__asm__ __volatile__( \
"mrc p15, 0, %0, c1, c0, 0 @ get CR" \
: "=r" (__val) : : "cc"); \
__val; \
})
extern unsigned long cr_no_alignment; /* defined in entry-armv.S */
extern unsigned long cr_alignment; /* defined in entry-armv.S */
#define UDBG_UNDEFINED (1 << 0)
#define UDBG_SYSCALL (1 << 1)
#define UDBG_BADABORT (1 << 2)
#define UDBG_SEGV (1 << 3)
#define UDBG_BUS (1 << 4)
extern unsigned int user_debug;
#if __LINUX_ARM_ARCH__ >= 4
#define vectors_high() (cr_alignment & CR_V)
#else
#define vectors_high() (0)
#endif
#define mb() __asm__ __volatile__ ("" : : : "memory")
#define rmb() mb()
#define wmb() mb()
#define read_barrier_depends() do { } while(0)
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
#ifdef CONFIG_SMP
/*
* Define our own context switch locking. This allows us to enable
* interrupts over the context switch, otherwise we end up with high
* interrupt latency. The real problem area is switch_mm() which may
* do a full cache flush.
*/
#define prepare_arch_switch(rq,next) \
do { \
spin_lock(&(next)->switch_lock); \
spin_unlock_irq(&(rq)->lock); \
} while (0)
#define finish_arch_switch(rq,prev) \
spin_unlock(&(prev)->switch_lock)
#define task_running(rq,p) \
((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
#else
/*
* Our UP-case is more simple, but we assume knowledge of how
* spin_unlock_irq() and friends are implemented. This avoids
* us needlessly decrementing and incrementing the preempt count.
*/
#define prepare_arch_switch(rq,next) local_irq_enable()
#define finish_arch_switch(rq,prev) spin_unlock(&(rq)->lock)
#define task_running(rq,p) ((rq)->curr == (p))
#endif
/*
* switch_to(prev, next) should switch from task `prev' to `next'
* `prev' will never be the same as `next'. schedule() itself
* contains the memory barrier to tell GCC not to cache `current'.
*/
extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
#define switch_to(prev,next,last) \
do { \
last = __switch_to(prev,prev->thread_info,next->thread_info); \
} while (0)
/*
* CPU interrupt mask handling.
*/
#if __LINUX_ARM_ARCH__ >= 6
#define local_irq_save(x) \
({ \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_irq_save\n" \
"cpsid i" \
: "=r" (x) : : "memory", "cc"); \
})
#define local_irq_enable() __asm__("cpsie i @ __sti" : : : "memory", "cc")
#define local_irq_disable() __asm__("cpsid i @ __cli" : : : "memory", "cc")
#define local_fiq_enable() __asm__("cpsie f @ __stf" : : : "memory", "cc")
#define local_fiq_disable() __asm__("cpsid f @ __clf" : : : "memory", "cc")
#else
/*
* Save the current interrupt enable state & disable IRQs
*/
#define local_irq_save(x) \
({ \
unsigned long temp; \
(void) (&temp == &x); \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_irq_save\n" \
" orr %1, %0, #128\n" \
" msr cpsr_c, %1" \
: "=r" (x), "=r" (temp) \
: \
: "memory", "cc"); \
})
/*
* Enable IRQs
*/
#define local_irq_enable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_irq_enable\n" \
" bic %0, %0, #128\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
/*
* Disable IRQs
*/
#define local_irq_disable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_irq_disable\n" \
" orr %0, %0, #128\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
/*
* Enable FIQs
*/
#define local_fiq_enable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ stf\n" \
" bic %0, %0, #64\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
/*
* Disable FIQs
*/
#define local_fiq_disable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ clf\n" \
" orr %0, %0, #64\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
#endif
/*
* Save the current interrupt enable state.
*/
#define local_save_flags(x) \
({ \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_save_flags" \
: "=r" (x) : : "memory", "cc"); \
})
/*
* restore saved IRQ & FIQ state
*/
#define local_irq_restore(x) \
__asm__ __volatile__( \
"msr cpsr_c, %0 @ local_irq_restore\n" \
: \
: "r" (x) \
: "memory", "cc")
#define irqs_disabled() \
({ \
unsigned long flags; \
local_save_flags(flags); \
flags & PSR_I_BIT; \
})
#ifdef CONFIG_SMP
#error SMP not supported
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
#define smp_read_barrier_depends() read_barrier_depends()
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while(0)
#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
/*
* On the StrongARM, "swp" is terminally broken since it bypasses the
* cache totally. This means that the cache becomes inconsistent, and,
* since we use normal loads/stores as well, this is really bad.
* Typically, this causes oopsen in filp_close, but could have other,
* more disasterous effects. There are two work-arounds:
* 1. Disable interrupts and emulate the atomic swap
* 2. Clean the cache, perform atomic swap, flush the cache
*
* We choose (1) since its the "easiest" to achieve here and is not
* dependent on the processor type.
*/
#define swp_is_buggy
#endif
static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
{
extern void __bad_xchg(volatile void *, int);
unsigned long ret;
#ifdef swp_is_buggy
unsigned long flags;
#endif
switch (size) {
#ifdef swp_is_buggy
case 1:
local_irq_save(flags);
ret = *(volatile unsigned char *)ptr;
*(volatile unsigned char *)ptr = x;
local_irq_restore(flags);
break;
case 4:
local_irq_save(flags);
ret = *(volatile unsigned long *)ptr;
*(volatile unsigned long *)ptr = x;
local_irq_restore(flags);
break;
#else
case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]"
: "=&r" (ret)
: "r" (x), "r" (ptr)
: "memory", "cc");
break;
case 4: __asm__ __volatile__ ("swp %0, %1, [%2]"
: "=&r" (ret)
: "r" (x), "r" (ptr)
: "memory", "cc");
break;
#endif
default: __bad_xchg(ptr, size), ret = 0;
}
return ret;
}
#endif /* CONFIG_SMP */
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif

View File

@@ -0,0 +1,15 @@
#ifndef _TPYES_H
#define _TPYES_H
#ifndef NULL
#define NULL 0
#endif
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif /* _SIZE_T */
#endif /* _TPYES_H */

View File

@@ -0,0 +1,46 @@
/*
* Use local definitions of C library macros and functions
* NOTE: The function implementations may not be as efficient
* as an inline or assembly code implementation provided by a
* native C library.
*/
#include "types.h"
#ifndef va_arg
#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif /* _VALIST */
/*
* Storage alignment properties
*/
#define NATIVE_INT int
#define _AUPBND (sizeof (NATIVE_INT) - 1)
#define _ADNBND (sizeof (NATIVE_INT) - 1)
/*
* Variable argument list macro definitions
*/
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
#endif /* va_arg */
unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
long simple_strtol(const char *cp,char **endp,unsigned int base);
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base);
long long simple_strtoll(const char *cp,char **endp,unsigned int base);
//static int skip_atoi(const char **s);
//char * number(char * buf, char * end, long long num, int base, int size, int precision, int type);
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
int snprintf(char * buf, size_t size, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args);
int sprintf(char * buf, const char *fmt, ...);
int vsscanf(const char * buf, const char * fmt, va_list args);
int sscanf(const char * buf, const char * fmt, ...);

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