Merge pull request #231 from OpenKemove/lpc11uxx-v20.x

[HAL] [LPC11Uxx]: Add Initial Support for LPC11Uxx series
This commit is contained in:
Fabien Poussin 2020-12-05 18:51:57 +01:00 committed by GitHub
commit b6db28f96b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 7623 additions and 6 deletions

View File

@ -2,19 +2,19 @@ Joel Bodenmann aka Tectu
https://github.com/Tectu
Git repository maintainer
Uladzimir Pylinsky aka barthess
Uladzimir Pylinsky aka barthess
https://github.com/barthess
Git repository maintainer
Marco Veeneman aka Marco
Marco Veeneman aka Marco
https://github.com/marcoveeneman
Maintainer of the ChibiOS port for the Texas Instruments
Maintainer of the ChibiOS port for the Texas Instruments
Tiva C Series Microcontrollers
Fabien Poussin aka fpoussin
Fabien Poussin aka fpoussin
https://github.com/fpoussin
Matthias Blaicher aka mabl
Matthias Blaicher aka mabl
https://github.com/mabl
Andrea Zoppi aka TexZK
@ -23,3 +23,6 @@ https://github.com/TexZK
Diego Ismirlian aka dismirlian
https://github.com/dismirlian
USB Host stack author
Yaotian Feng aka Codetector
https://github.com/Codetector1374

28
Jenkinsfile vendored
View File

@ -149,7 +149,33 @@ export CHC_PATH=$WORKSPACE
'''
}
}
stage('Build LPC') {
agent {
docker {
image 'fpoussin/jenkins:ubuntu-18.04-chibios'
}
}
steps {
sh '''arm-none-eabi-gcc -v
cd $WORKSPACE/ext
for i in *.7z; do 7z x -y $i; done
cd $WORKSPACE
rm -rf $CH_PATH
git clone /var/lib/git/ChibiOS $CH_PATH
cd $CH_PATH
git remote set-url origin https://github.com/ChibiOS/ChibiOS.git
git fetch --all
git checkout -b $CH_BRANCH origin/$CH_BRANCH
git pull --rebase origin $CH_BRANCH
cd ext
for i in *.7z; do 7z x -y $i; done'''
sh '''export CH_PATH=$WORKSPACE/ChibiOS
export CHC_PATH=$WORKSPACE
./tools/chbuild.sh ./demos/LPC/
'''
}
}
}
}
@ -158,4 +184,4 @@ export CHC_PATH=$WORKSPACE
CH_BRANCH = 'stable_20.3.x'
CH_PATH = 'ChibiOS'
}
}
}

5
demos/LPC/LPC_11U35_USBDFU/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.dep/
build/
.vscode/
.idea/

View File

@ -0,0 +1,191 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O1 -g -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data.
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO).
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
USE_SMART_BUILD = yes
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
# Enables the use of FPU (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
# FPU-related options.
ifeq ($(USE_FPU_OPT),)
USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, target, sources and paths
#
# Define project name here
PROJECT = lpc_boot
# Target settings.
MCU = cortex-m0
# Imported source files and paths.
CHIBIOS = ../../../../ChibiOS
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
CONFDIR := ./cfg
BUILDDIR := ./build
DEPDIR := ./.dep
BOARDDIR := ./board
# Licensing files.
include $(CHIBIOS)/os/license/license.mk
# Startup files.
include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_lpc11uxx.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LPC11Uxx/platform.mk
include $(BOARDDIR)/board.mk
include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
# Auto-build files in ./source recursively.
include $(CHIBIOS)/tools/mk/autobuild.mk
# Other files (optional).
#include $(CHIBIOS)/test/lib/test.mk
#include $(CHIBIOS)/test/rt/rt_test.mk
#include $(CHIBIOS)/test/oslib/oslib_test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD_CONTRIB)/LPC11U35_401.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(ALLCSRC) \
$(TESTSRC) \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC = $(ALLCPPSRC)
# List ASM source files here.
ASMSRC = $(ALLASMSRC)
# List ASM with preprocessor source files here.
ASMXSRC = $(ALLXASMSRC)
# Inclusion directories.
INCDIR = $(CONFDIR) $(ALLINC) $(TESTINC)
# Define C warning options here.
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
# Define C++ warning options here.
CPPWARN = -Wall -Wextra -Wundef
#
# Project, target, sources and paths
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS = -DLPC11U35 -DPORT_IGNORE_GCC_VERSION_CHECK
# Define ASM defines here
UADEFS = -DLPC11U35 -DPORT_IGNORE_GCC_VERSION_CHECK
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user section
##############################################################################
##############################################################################
# Common rules
#
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk
include $(RULESPATH)/arm-none-eabi.mk
include $(RULESPATH)/rules.mk
#
# Common rules
##############################################################################
##############################################################################
# Custom rules
#
#
# Custom rules
##############################################################################

View File

@ -0,0 +1,10 @@
#include "board.h"
#include "hal.h"
#define MATRIX_ROWS 8
#define MATRIX_COLS 9
void boardInit(void) {
palSetLineMode(LINE_USBVBUS, MODE_FUNC_ALT1 | MODE_MODE_PULL_UP | MODE_AD_DIGITAL);
palSetLineMode(LINE_USBCONN, MODE_FUNC_ALT1 | MODE_AD_DIGITAL);
}

View File

@ -0,0 +1,60 @@
#pragma once
/*
ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* This file has been automatically generated using ChibiStudio board
* generator plugin. Do not edit manually.
*/
#ifndef BOARD_H
#define BOARD_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*
* Setup for mTrain board.
*/
/*
* Board identifier.
*/
#define BOARD_KEMOVE_SNOWFOX
#define BOARD_NAME "Kemove Snowfox"
#ifndef LPC11U35
#define LPC11U35
#endif
#define LINE_USBCONN PAL_LINE(IOPORT0, 6)
#define LINE_USBVBUS PAL_LINE(IOPORT0, 3)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* BOARD_H */

View File

@ -0,0 +1,9 @@
# List of all the board related files.
BOARDSRC = $(BOARDDIR)/board.c
# Required include directories
BOARDINC = $(BOARDDIR)
# Shared variables
ALLCSRC += $(BOARDSRC)
ALLINC += $(BOARDINC)

View File

@ -0,0 +1,757 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file rt/templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef CHCONF_H
#define CHCONF_H
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_6_1_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION 32
#endif
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#if !defined(CH_CFG_ST_FREQUENCY)
#define CH_CFG_ST_FREQUENCY 10000
#endif
/**
* @brief Time intervals data size.
* @note Allowed values are 16, 32 or 64 bits.
*/
#if !defined(CH_CFG_INTERVALS_SIZE)
#define CH_CFG_INTERVALS_SIZE 32
#endif
/**
* @brief Time types data size.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_TIME_TYPES_SIZE)
#define CH_CFG_TIME_TYPES_SIZE 32
#endif
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#if !defined(CH_CFG_ST_TIMEDELTA)
#define CH_CFG_ST_TIMEDELTA 2
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#if !defined(CH_CFG_TIME_QUANTUM)
#define CH_CFG_TIME_QUANTUM 0
#endif
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#if !defined(CH_CFG_NO_IDLE_THREAD)
#define CH_CFG_NO_IDLE_THREAD FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_OPTIMIZE_SPEED)
#define CH_CFG_OPTIMIZE_SPEED TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_TM)
#define CH_CFG_USE_TM FALSE
#endif
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_REGISTRY)
#define CH_CFG_USE_REGISTRY TRUE
#endif
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_WAITEXIT)
#define CH_CFG_USE_WAITEXIT TRUE
#endif
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_SEMAPHORES)
#define CH_CFG_USE_SEMAPHORES TRUE
#endif
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
#endif
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MUTEXES)
#define CH_CFG_USE_MUTEXES TRUE
#endif
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
#endif
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_CONDVARS)
#define CH_CFG_USE_CONDVARS TRUE
#endif
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
#endif
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_EVENTS)
#define CH_CFG_USE_EVENTS TRUE
#endif
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
#endif
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MESSAGES)
#define CH_CFG_USE_MESSAGES TRUE
#endif
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
#endif
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#if !defined(CH_CFG_USE_DYNAMIC)
#define CH_CFG_USE_DYNAMIC TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name OSLIB options
* @{
*/
/*===========================================================================*/
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_MAILBOXES)
#define CH_CFG_USE_MAILBOXES TRUE
#endif
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMCORE)
#define CH_CFG_USE_MEMCORE TRUE
#endif
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#if !defined(CH_CFG_MEMCORE_SIZE)
#define CH_CFG_MEMCORE_SIZE 0
#endif
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_CFG_USE_HEAP)
#define CH_CFG_USE_HEAP TRUE
#endif
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMPOOLS)
#define CH_CFG_USE_MEMPOOLS TRUE
#endif
/**
* @brief Objects FIFOs APIs.
* @details If enabled then the objects FIFOs APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_OBJ_FIFOS)
#define CH_CFG_USE_OBJ_FIFOS TRUE
#endif
/**
* @brief Pipes APIs.
* @details If enabled then the pipes APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_PIPES)
#define CH_CFG_USE_PIPES TRUE
#endif
/**
* @brief Objects Caches APIs.
* @details If enabled then the objects caches APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_OBJ_CACHES)
#define CH_CFG_USE_OBJ_CACHES TRUE
#endif
/**
* @brief Delegate threads APIs.
* @details If enabled then the delegate threads APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_DELEGATES)
#define CH_CFG_USE_DELEGATES TRUE
#endif
/**
* @brief Jobs Queues APIs.
* @details If enabled then the jobs queues APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_JOBS)
#define CH_CFG_USE_JOBS TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Objects factory options
* @{
*/
/*===========================================================================*/
/**
* @brief Objects Factory APIs.
* @details If enabled then the objects factory APIs are included in the
* kernel.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_CFG_USE_FACTORY)
#define CH_CFG_USE_FACTORY TRUE
#endif
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
#endif
/**
* @brief Enables the registry of generic objects.
*/
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#endif
/**
* @brief Enables factory for generic buffers.
*/
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#endif
/**
* @brief Enables factory for semaphores.
*/
#if !defined(CH_CFG_FACTORY_SEMAPHORES)
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#endif
/**
* @brief Enables factory for mailboxes.
*/
#if !defined(CH_CFG_FACTORY_MAILBOXES)
#define CH_CFG_FACTORY_MAILBOXES TRUE
#endif
/**
* @brief Enables factory for objects FIFOs.
*/
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#endif
/**
* @brief Enables factory for Pipes.
*/
#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_PIPES TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_STATISTICS)
#define CH_DBG_STATISTICS FALSE
#endif
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
#define CH_DBG_SYSTEM_STATE_CHECK FALSE
#endif
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS)
#define CH_DBG_ENABLE_CHECKS FALSE
#endif
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS)
#define CH_DBG_ENABLE_ASSERTS FALSE
#endif
/**
* @brief Debug option, trace buffer.
* @details If enabled then the trace buffer is activated.
*
* @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_MASK)
#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
#endif
/**
* @brief Trace buffer entries.
* @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
* different from @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
#define CH_DBG_TRACE_BUFFER_SIZE 128
#endif
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK)
#define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS)
#define CH_DBG_FILL_THREADS FALSE
#endif
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#if !defined(CH_DBG_THREADS_PROFILING)
#define CH_DBG_THREADS_PROFILING FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief System structure extension.
* @details User fields added to the end of the @p ch_system_t structure.
*/
#define CH_CFG_SYSTEM_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief System initialization hook.
* @details User initialization code added to the @p chSysInit() function
* just before interrupts are enabled globally.
*/
#define CH_CFG_SYSTEM_INIT_HOOK() { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p _thread_init() function.
*
* @note It is invoked from within @p _thread_init() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief ISR enter hook.
*/
#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
/* IRQ prologue code here.*/ \
}
/**
* @brief ISR exit hook.
*/
#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
/* IRQ epilogue code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
/* Idle-enter code here.*/ \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
/* Idle-leave code here.*/ \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/**
* @brief Trace hook.
* @details This hook is invoked each time a new record is written in the
* trace buffer.
*/
#define CH_CFG_TRACE_HOOK(tep) { \
/* Trace code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* CHCONF_H */
/** @} */

View File

@ -0,0 +1,532 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef HALCONF_H
#define HALCONF_H
#define _CHIBIOS_HAL_CONF_
#define _CHIBIOS_HAL_CONF_VER_7_1_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the cryptographic subsystem.
*/
#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__)
#define HAL_USE_CRY FALSE
#endif
/**
* @brief Enables the DAC subsystem.
*/
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC FALSE
#endif
/**
* @brief Enables the EFlash subsystem.
*/
#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__)
#define HAL_USE_EFL FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL FALSE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SIO subsystem.
*/
#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__)
#define HAL_USE_SIO FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the TRNG subsystem.
*/
#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
#define HAL_USE_TRNG FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB TRUE
#endif
/**
* @brief Enables the WDG subsystem.
*/
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
#define HAL_USE_WDG FALSE
#endif
/**
* @brief Enables the WSPI subsystem.
*/
#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__)
#define HAL_USE_WSPI FALSE
#endif
/*===========================================================================*/
/* PAL driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
#define PAL_USE_CALLBACKS FALSE
#endif
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
#define PAL_USE_WAIT FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT FALSE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE FALSE
#endif
/**
* @brief Enforces the driver to use direct callbacks rather than OSAL events.
*/
#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
#define CAN_ENFORCE_USE_CALLBACKS FALSE
#endif
/*===========================================================================*/
/* CRY driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the SW fall-back of the cryptographic driver.
* @details When enabled, this option, activates a fall-back software
* implementation for algorithms not supported by the underlying
* hardware.
* @note Fall-back implementations may not be present for all algorithms.
*/
#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
#define HAL_CRY_USE_FALLBACK FALSE
#endif
/**
* @brief Makes the driver forcibly use the fall-back implementations.
*/
#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
#define HAL_CRY_ENFORCE_FALLBACK FALSE
#endif
/*===========================================================================*/
/* DAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
#define DAC_USE_WAIT FALSE
#endif
/**
* @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define DAC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the zero-copy API.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS FALSE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING FALSE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/**
* @brief OCR initialization constant for V20 cards.
*/
#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
#define SDC_INIT_OCR_V20 0x50FF8000U
#endif
/**
* @brief OCR initialization constant for non-V20 cards.
*/
#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
#define SDC_INIT_OCR 0x80100000U
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 16 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 256 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/**
* @brief Serial over USB number of buffers.
* @note The default is 2 buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_NUMBER 2
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables circular transfers APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
#define SPI_USE_CIRCULAR FALSE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
/**
* @brief Handling method for SPI CS line.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
#endif
/*===========================================================================*/
/* UART driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
#define UART_USE_WAIT FALSE
#endif
/**
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define UART_USE_MUTUAL_EXCLUSION FALSE
#endif
/*===========================================================================*/
/* USB driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
#define USB_USE_WAIT TRUE
#endif
/*===========================================================================*/
/* WSPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
#define WSPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define WSPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#endif /* HALCONF_H */
/** @} */

View File

@ -0,0 +1,17 @@
#ifndef MCUCONF_H
#define MCUCONF_H
#define LPC11U35_MCUCONF
#define LPC_USE_SYSOSC TRUE
#define LPC_SYSOSC_FREQUENCY 12000000UL // 12MHz
#define LPC_SYSPLLCLKSEL SYSCON_SYSPLLCLKSEL_SYSOSC
#define LPC_MAINCLKSEL SYSCON_MAINCLKSEL_PLLOUT
#define LPC_SYSPLL_MULT 4 // MVALUE 4 -> bits 0b00011
#define LPC_SYSPLL_PDIV 4 // PSEL 2 -> bits 0b01
#define LPC_SYS_DIV 1 // NO SYS DIV
#define LPC_USB_USE_USB1 TRUE
#define LPC_USB_USB1_IRQ_PRIORITY 3
#endif

View File

@ -0,0 +1,122 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ch.h"
#include "hal.h"
#include "usbdfu.h"
#include <string.h>
#define CM_RESET_VECTOR_OFFSET 4
static void jump_to_application(void) __attribute__ ((noreturn));
static void jump_to_application(void) {
/* Use the application's vector table */
// Copy Vector Table to RAM_START(0x10000000)
memcpy((void*) 0x10000000, (void*)APP_BASE, 512);
// Switch Vector Table
LPC_SYSCON->SYSMEMREMAP = 0x1; // User RAM mode
/* Initialize the application's stack pointer */
__set_MSP(*((volatile uint32_t*)(APP_BASE)));
uint32_t target_start = *((volatile uint32_t*)(APP_BASE + CM_RESET_VECTOR_OFFSET));
uint32_t initial_sp = *((volatile uint32_t*)(APP_BASE));
/* Jump to the application entry point */
__ASM volatile ("mov sp, %0\n" "bx %1" : : "r" (initial_sp), "r" (target_start) : );
while (1) {}
}
#define IAP_LOCATION 0x1fff1ff1
typedef void (*IAP)(uint32_t [], uint32_t []);
const IAP iap_entry = (IAP)IAP_LOCATION;
/*
* Application entry point.
*/
int main(void) {
halInit();
/*
* System initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
chSysInit();
memset(fw_buffer, 0, FW_BUFFER_SIZE);
dfu_need_flush = 0;
/*
* Normal main() thread activity, in this demo it does nothing except
* increasing the minutes counter.
*/
while (true) {
uint32_t iap_command[5];
uint32_t iap_result[4];
usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(1500);
usbStart(&USBD1, &usbcfg);
usbConnectBus(&USBD1);
while(1){
if (dfu_need_flush) {
if (global_offset == APP_BASE) {
do {
iap_command[0] = 50; // Prep Sector
iap_command[1] = 3; // Start Sec
iap_command[2] = 15; // Stop Sec
iap_entry(iap_command, iap_result);
} while(iap_result[0]);
// Erase All Flash (3-15)
do {
iap_command[0] = 52; // Erase Sector
iap_command[1] = 3; // Start Sec
iap_command[2] = 15; // Stop Sec
iap_command[3] = 48000; // 48MHz
iap_entry(iap_command, iap_result);
} while(iap_result[0]);
}
uint32_t start_sector = global_offset / 4096;
uint32_t end_sector = (global_offset + FW_BUFFER_SIZE) / 4096;
iap_command[0] = 50; // Prep Sector
iap_command[1] = start_sector; // Start Sec
iap_command[2] = end_sector; // Stop Sec
iap_entry(iap_command, iap_result);
// Copy the buffer
iap_command[0] = 51;
iap_command[1] = global_offset;
iap_command[2] = (uint32_t)fw_buffer;
iap_command[3] = FW_BUFFER_SIZE;
iap_command[4] = 48000;
iap_entry(iap_command, iap_result);
global_offset += FW_BUFFER_SIZE;
dfu_need_flush = 0;
memset(fw_buffer, 0, FW_BUFFER_SIZE);
buffer_fill = 0;
if (currentState == STATE_DFU_DNLOAD_SYNC || currentState == STATE_DFU_DNBUSY)
currentState = STATE_DFU_DNLOAD_IDLE;
if (currentState == STATE_DFU_MANIFEST_SYNC) {
currentState = STATE_DFU_MANIFEST_WAIT_RESET;
chThdSleepMilliseconds(2000);
jump_to_application();
}
}
}
}
}

View File

@ -0,0 +1,13 @@
# Open Kemove - DFU Firmware Loader
This repository contains a *beta* bootloader that implements the USB-DFU protocol
for the kemove snowfox keyboard. (Or any LPC11U35/401) for tha matter.
The bootloader expect to be loaded at flash address 0x0000_0000. You can do this
by putting the controller into ISP mode, and drag drop the firmware bin file
onto the controller drive.
If you want to build custom firmware using this loader, please have your firmware
expect to be loaded at 0x3000. Also do no use the first 512 bytes of RAM. It will
be used for reset/interrupt vector table. The table will be copied to first
512 bytes of ram.

View File

@ -0,0 +1,225 @@
#include "hal.h"
#include "usbdfu.h"
uint8_t fw_buffer[FW_BUFFER_SIZE];
volatile uint8_t dfu_need_flush = 0;
volatile uint32_t buffer_fill = 0;
volatile uint32_t global_offset = APP_BASE;
/*
* USB Device Descriptor.
*/
static const uint8_t dfu_device_descriptor_data[18] = {
USB_DESC_DEVICE (0x0200, /* bcdUSB (1.1). */
0x00, /* bDeviceClass */
0x00, /* bDeviceSubClass. */
0x00, /* bDeviceProtocol. */
64, /* bMaxPacketSize. */
0xfeed, /* idVendor (ST). */
0x6969, /* idProduct. */
0x0200, /* bcdDevice. */
1, /* iManufacturer. */
2, /* iProduct. */
3, /* iSerialNumber. */
1) /* bNumConfigurations. */
};
static const USBDescriptor dfu_device_descriptor = {
sizeof dfu_device_descriptor_data,
dfu_device_descriptor_data
};
/* Configuration Descriptor tree for a DFU.*/
static const uint8_t dfu_configuration_descriptor_data[27] = {
/* Configuration Descriptor.*/
USB_DESC_CONFIGURATION(27, /* wTotalLength. */
0x01, /* bNumInterfaces. */
0x01, /* bConfigurationValue. */
0, /* iConfiguration. */
0xC0, /* bmAttributes (self powered). */
50), /* bMaxPower (100mA). */
/* Interface Descriptor.*/
USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x00, /* bNumEndpoints. */
0xFE, /* bInterfaceClass (DFU Class
*/
0x01, /* bInterfaceSubClass */
0x02, /* bInterfaceProtocol */
0), /* iInterface. */
/* DFU Class Descriptor.*/
USB_DESC_BYTE (9), /* bLength. */
USB_DESC_BYTE (0x21), /* bDescriptorType (DFU_FCUNTION). */
USB_DESC_BYTE (0b1011), /* bmAttributes (DETACH | DOWNLOAD) */
USB_DESC_WORD ( 1500), /* Timeout. */
USB_DESC_WORD (64 ),
USB_DESC_BCD (0x0110)
};
static const USBDescriptor dfu_configuration_descriptor = {
sizeof dfu_configuration_descriptor_data,
dfu_configuration_descriptor_data
};
static const uint8_t dfu_string0[] = {
USB_DESC_BYTE(4), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
};
static const uint8_t dfu_string1[] = {
USB_DESC_BYTE(22), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'O', 0, 'p', 0, 'e', 0, 'n', 0, 'K', 0, 'e', 0, 'm', 0, 'o', 0,
'v', 0, 'e', 0
};
/*
* Device Description string.
*/
static const uint8_t dfu_string2[] = {
USB_DESC_BYTE(8), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'D', 0, 'F', 0, 'U', 0
};
/*
* Serial Number string.
*/
static const uint8_t dfu_string3[] = {
USB_DESC_BYTE(8), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'0' + CH_KERNEL_MAJOR, 0,
'0' + CH_KERNEL_MINOR, 0,
'0' + CH_KERNEL_PATCH, 0
};
/*
* Strings wrappers array.
*/
static const USBDescriptor dfu_strings[] = {
{sizeof dfu_string0, dfu_string0},
{sizeof dfu_string1, dfu_string1},
{sizeof dfu_string2, dfu_string2},
{sizeof dfu_string3, dfu_string3}
};
/*
* Handles the GET_DESCRIPTOR callback. All required descriptors must be
* handled here.
*/
static const USBDescriptor *get_descriptor(USBDriver *usbp,
uint8_t dtype,
uint8_t dindex,
uint16_t lang) {
(void)usbp;
(void)lang;
switch (dtype) {
case USB_DESCRIPTOR_DEVICE:
return &dfu_device_descriptor;
case USB_DESCRIPTOR_CONFIGURATION:
return &dfu_configuration_descriptor;
case USB_DESCRIPTOR_STRING:
if (dindex < 4)
return &dfu_strings[dindex];
}
return NULL;
}
static void usb_event(USBDriver *usbp, usbevent_t event) {
}
static void sof_handler(USBDriver *usbp) {
(void)usbp;
}
volatile enum dfu_state currentState = STATE_DFU_IDLE;
size_t currentAddress = 0;
static enum {
LASTOP_IDLE,
LASTOP_DNLOAD,
LASTOP_UPLOAD
} lastOperation;
static uint8_t status_response_buffer[6] = {
DFU_STATUS_OK, // Status (0)
100, 0x00, 0x00,
0x00, // Next State (4)
0
};
static bool request_handler(USBDriver *usbp) {
if((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
uint16_t transfer_size = (((uint16_t)usbp->setup[7]) << 8) | usbp->setup[6];
uint16_t block_cnt = (((uint16_t)usbp->setup[4]) << 8) | usbp->setup[3];
switch (usbp->setup[1]) {
case DFU_GETSTATUS:
if (currentState == STATE_DFU_DNLOAD_SYNC) {
currentState = STATE_DFU_DNBUSY;
}
status_response_buffer[4] = currentState;
usbSetupTransfer(usbp, (uint8_t *)status_response_buffer, 6, NULL);
return true;
case DFU_GETSTATE:
usbSetupTransfer(usbp, (uint8_t *)&currentState, 1, NULL);
return true;
case DFU_UPLOAD:
if (lastOperation != LASTOP_UPLOAD) {
lastOperation = LASTOP_UPLOAD;
currentAddress = APP_BASE;
}
if ((currentAddress + transfer_size) > MAX_FLASH_ADDR) {
transfer_size = MAX_FLASH_ADDR - currentAddress;
usbSetupTransfer(usbp, (uint8_t *)currentAddress, transfer_size, NULL);
lastOperation = LASTOP_IDLE;
currentState = STATE_DFU_IDLE;
} else {
usbSetupTransfer(usbp, (uint8_t *)currentAddress, transfer_size, NULL);
currentAddress += transfer_size;
currentState = STATE_DFU_UPLOAD_IDLE;
}
return true;
case DFU_ABORT:
lastOperation = LASTOP_IDLE;
currentState = STATE_DFU_IDLE;
return true;
case DFU_DNLOAD:
if (lastOperation != LASTOP_DNLOAD) {
lastOperation = LASTOP_DNLOAD;
global_offset = APP_BASE;
buffer_fill = 0;
dfu_need_flush = 0;
}
if (transfer_size) {
usbSetupTransfer(usbp, &fw_buffer[buffer_fill], transfer_size, NULL);
buffer_fill += transfer_size;
if (buffer_fill < FW_BUFFER_SIZE) {
currentState = STATE_DFU_DNLOAD_IDLE;
} else {
currentState = STATE_DFU_DNLOAD_SYNC;
dfu_need_flush = 1;
}
} else {
if (buffer_fill > 0)
dfu_need_flush = 1;
currentState = STATE_DFU_MANIFEST_SYNC;
lastOperation = LASTOP_IDLE;
}
return true;
}
}
return false;
}
/*
* USB driver configuration.
*/
const USBConfig usbcfg = {
usb_event,
get_descriptor,
request_handler,
sof_handler
};

View File

@ -0,0 +1,65 @@
#pragma once
#include "stdint.h"
extern const USBConfig usbcfg;
#define MAX_FLASH_ADDR 0x10000
#define FLASH_BASE 0x0
#define BL_SIZE 0x3000
#define APP_BASE (FLASH_BASE + BL_SIZE)
#define FLASH_PAGE_SIZE 4096
#define FW_BUFFER_SIZE 1024
extern uint8_t fw_buffer[FW_BUFFER_SIZE];
extern volatile uint8_t dfu_need_flush;
extern volatile uint32_t buffer_fill;
extern volatile uint32_t global_offset;
extern size_t currentAddress;
extern volatile enum dfu_state currentState;
enum dfu_req {
DFU_DETACH,
DFU_DNLOAD,
DFU_UPLOAD,
DFU_GETSTATUS,
DFU_CLRSTATUS,
DFU_GETSTATE,
DFU_ABORT,
};
enum dfu_state {
STATE_APP_IDLE,
STATE_APP_DETACH,
STATE_DFU_IDLE,
STATE_DFU_DNLOAD_SYNC,
STATE_DFU_DNBUSY,
STATE_DFU_DNLOAD_IDLE,
STATE_DFU_MANIFEST_SYNC,
STATE_DFU_MANIFEST,
STATE_DFU_MANIFEST_WAIT_RESET,
STATE_DFU_UPLOAD_IDLE,
STATE_DFU_ERROR,
};
enum dfu_status {
DFU_STATUS_OK,
DFU_STATUS_ERR_TARGET,
DFU_STATUS_ERR_FILE,
DFU_STATUS_ERR_WRITE,
DFU_STATUS_ERR_ERASE,
DFU_STATUS_ERR_CHECK_ERASED,
DFU_STATUS_ERR_PROG,
DFU_STATUS_ERR_VERIFY,
DFU_STATUS_ERR_ADDRESS,
DFU_STATUS_ERR_NOTDONE,
DFU_STATUS_ERR_FIRMWARE,
DFU_STATUS_ERR_VENDOR,
DFU_STATUS_ERR_USBR,
DFU_STATUS_ERR_POR,
DFU_STATUS_ERR_UNKNOWN,
DFU_STATUS_ERR_STALLEDPKT,
};

View File

@ -0,0 +1,824 @@
/****************************************************************************************************//**
* @file LPC11Uxx.h
*
*
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File for
* default LPC11Uxx Device Series
*
* @version V0.1
* @date 21. March 2011
*
* @note Generated with SFDGen V2.6 Build 3j (beta) on Thursday, 17.03.2011 13:19:45
*
* from CMSIS SVD File 'LPC11U1x_svd.xml' Version 0.1,
* created on Wednesday, 16.03.2011 20:30:42, last modified on Thursday, 17.03.2011 20:19:40
*
*******************************************************************************************************/
/** @addtogroup NXP
* @{
*/
/** @addtogroup LPC11Uxx
* @{
*/
#ifndef __LPC11UXX_H__
#define __LPC11UXX_H__
#ifdef __cplusplus
extern "C" {
#endif
#if defined ( __CC_ARM )
#pragma anon_unions
#endif
/* Interrupt Number Definition */
typedef enum {
// ------------------------- Cortex-M0 Processor Exceptions Numbers -----------------------------
Reset_IRQn = -15, /*!< 1 Reset Vector, invoked on Power up and warm reset */
NonMaskableInt_IRQn = -14, /*!< 2 Non maskable Interrupt, cannot be stopped or preempted */
HardFault_IRQn = -13, /*!< 3 Hard Fault, all classes of Fault */
SVCall_IRQn = -5, /*!< 11 System Service Call via SVC instruction */
DebugMonitor_IRQn = -4, /*!< 12 Debug Monitor */
PendSV_IRQn = -2, /*!< 14 Pendable request for system service */
SysTick_IRQn = -1, /*!< 15 System Tick Timer */
// --------------------------- LPC11Uxx Specific Interrupt Numbers ------------------------------
FLEX_INT0_IRQn = 0, /*!< All I/O pins can be routed to below 8 interrupts. */
FLEX_INT1_IRQn = 1,
FLEX_INT2_IRQn = 2,
FLEX_INT3_IRQn = 3,
FLEX_INT4_IRQn = 4,
FLEX_INT5_IRQn = 5,
FLEX_INT6_IRQn = 6,
FLEX_INT7_IRQn = 7,
GINT0_IRQn = 8, /*!< Grouped Interrupt 0 */
GINT1_IRQn = 9, /*!< Grouped Interrupt 1 */
Reserved0_IRQn = 10, /*!< Reserved Interrupt */
Reserved1_IRQn = 11,
Reserved2_IRQn = 12,
Reserved3_IRQn = 13,
SSP1_IRQn = 14, /*!< SSP1 Interrupt */
I2C_IRQn = 15, /*!< I2C Interrupt */
TIMER_16_0_IRQn = 16, /*!< 16-bit Timer0 Interrupt */
TIMER_16_1_IRQn = 17, /*!< 16-bit Timer1 Interrupt */
TIMER_32_0_IRQn = 18, /*!< 32-bit Timer0 Interrupt */
TIMER_32_1_IRQn = 19, /*!< 32-bit Timer1 Interrupt */
SSP0_IRQn = 20, /*!< SSP0 Interrupt */
UART_IRQn = 21, /*!< UART Interrupt */
USB_IRQn = 22, /*!< USB IRQ Interrupt */
USB_FIQn = 23, /*!< USB FIQ Interrupt */
ADC_IRQn = 24, /*!< A/D Converter Interrupt */
WDT_IRQn = 25, /*!< Watchdog timer Interrupt */
BOD_IRQn = 26, /*!< Brown Out Detect(BOD) Interrupt */
FMC_IRQn = 27, /*!< Flash Memory Controller Interrupt */
Reserved4_IRQn = 28, /*!< Reserved Interrupt */
Reserved5_IRQn = 29, /*!< Reserved Interrupt */
USBWakeup_IRQn = 30, /*!< USB wakeup Interrupt */
Reserved6_IRQn = 31, /*!< Reserved Interrupt */
} IRQn_Type;
/** @addtogroup Configuration_of_CMSIS
* @{
*/
/* Processor and Core Peripheral Section */ /* Configuration of the Cortex-M0 Processor and Core Peripherals */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
/** @} */ /* End of group Configuration_of_CMSIS */
#include "core_cm0.h" /*!< Cortex-M0 processor and core peripherals */
/** @addtogroup Device_Peripheral_Registers
* @{
*/
// ------------------------------------------------------------------------------------------------
// ----- I2C -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x I2C-bus controller Modification date=3/16/2011 Major revision=0 Minor revision=3 (I2C)
*/
typedef struct { /*!< (@ 0x40000000) I2C Structure */
__IO uint32_t CONSET; /*!< (@ 0x40000000) I2C Control Set Register */
__I uint32_t STAT; /*!< (@ 0x40000004) I2C Status Register */
__IO uint32_t DAT; /*!< (@ 0x40000008) I2C Data Register. */
__IO uint32_t ADR0; /*!< (@ 0x4000000C) I2C Slave Address Register 0 */
__IO uint32_t SCLH; /*!< (@ 0x40000010) SCH Duty Cycle Register High Half Word */
__IO uint32_t SCLL; /*!< (@ 0x40000014) SCL Duty Cycle Register Low Half Word */
__IO uint32_t CONCLR; /*!< (@ 0x40000018) I2C Control Clear Register*/
__IO uint32_t MMCTRL; /*!< (@ 0x4000001C) Monitor mode control register*/
__IO uint32_t ADR1; /*!< (@ 0x40000020) I2C Slave Address Register 1*/
__IO uint32_t ADR2; /*!< (@ 0x40000024) I2C Slave Address Register 2*/
__IO uint32_t ADR3; /*!< (@ 0x40000028) I2C Slave Address Register 3*/
__I uint32_t DATA_BUFFER; /*!< (@ 0x4000002C) Data buffer register */
union{
__IO uint32_t MASK[4]; /*!< (@ 0x40000030) I2C Slave address mask register */
struct{
__IO uint32_t MASK0;
__IO uint32_t MASK1;
__IO uint32_t MASK2;
__IO uint32_t MASK3;
};
};
} LPC_I2C_Type;
// ------------------------------------------------------------------------------------------------
// ----- WWDT -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x Windowed Watchdog Timer (WWDT) Modification date=3/16/2011 Major revision=0 Minor revision=3 (WWDT)
*/
typedef struct { /*!< (@ 0x40004000) WWDT Structure */
__IO uint32_t MOD; /*!< (@ 0x40004000) Watchdog mode register*/
__IO uint32_t TC; /*!< (@ 0x40004004) Watchdog timer constant register */
__IO uint32_t FEED; /*!< (@ 0x40004008) Watchdog feed sequence register */
__I uint32_t TV; /*!< (@ 0x4000400C) Watchdog timer value register */
__IO uint32_t CLKSEL; /*!< (@ 0x40004010) Watchdog clock select register. */
__IO uint32_t WARNINT; /*!< (@ 0x40004014) Watchdog Warning Interrupt compare value. */
__IO uint32_t WINDOW; /*!< (@ 0x40004018) Watchdog Window compare value. */
} LPC_WWDT_Type;
// ------------------------------------------------------------------------------------------------
// ----- USART -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x USART Modification date=3/16/2011 Major revision=0 Minor revision=3 (USART)
*/
typedef struct { /*!< (@ 0x40008000) USART Structure */
union {
__IO uint32_t DLL; /*!< (@ 0x40008000) Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB=1) */
__O uint32_t THR; /*!< (@ 0x40008000) Transmit Holding Register. The next character to be transmitted is written here. (DLAB=0) */
__I uint32_t RBR; /*!< (@ 0x40008000) Receiver Buffer Register. Contains the next received character to be read. (DLAB=0) */
};
union {
__IO uint32_t IER; /*!< (@ 0x40008004) Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential USART interrupts. (DLAB=0) */
__IO uint32_t DLM; /*!< (@ 0x40008004) Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB=1) */
};
union {
__O uint32_t FCR; /*!< (@ 0x40008008) FIFO Control Register. Controls USART FIFO usage and modes. */
__I uint32_t IIR; /*!< (@ 0x40008008) Interrupt ID Register. Identifies which interrupt(s) are pending. */
};
__IO uint32_t LCR; /*!< (@ 0x4000800C) Line Control Register. Contains controls for frame formatting and break generation. */
__IO uint32_t MCR; /*!< (@ 0x40008010) Modem Control Register. */
__I uint32_t LSR; /*!< (@ 0x40008014) Line Status Register. Contains flags for transmit and receive status, including line errors. */
__I uint32_t MSR; /*!< (@ 0x40008018) Modem Status Register. */
__IO uint32_t SCR; /*!< (@ 0x4000801C) Scratch Pad Register. Eight-bit temporary storage for software. */
__IO uint32_t ACR; /*!< (@ 0x40008020) Auto-baud Control Register. Contains controls for the auto-baud feature. */
__IO uint32_t ICR; /*!< (@ 0x40008024) IrDA Control Register. Enables and configures the IrDA (remote control) mode. */
__IO uint32_t FDR; /*!< (@ 0x40008028) Fractional Divider Register. Generates a clock input for the baud rate divider. */
__IO uint32_t OSR; /*!< (@ 0x4000802C) Oversampling Register. Controls the degree of oversampling during each bit time. */
__IO uint32_t TER; /*!< (@ 0x40008030) Transmit Enable Register. Turns off USART transmitter for use with software flow control. */
__I uint32_t RESERVED0[3];
__IO uint32_t HDEN; /*!< (@ 0x40008040) Half duplex enable register. */
__I uint32_t RESERVED1;
__IO uint32_t SCICTRL; /*!< (@ 0x40008048) Smart Card Interface Control register. Enables and configures the Smart Card Interface feature. */
__IO uint32_t RS485CTRL; /*!< (@ 0x4000804C) RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */
__IO uint32_t RS485ADRMATCH; /*!< (@ 0x40008050) RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */
__IO uint32_t RS485DLY; /*!< (@ 0x40008054) RS-485/EIA-485 direction control delay. */
__IO uint32_t SYNCCTRL;
} LPC_USART_Type;
#define USART_FCR_FIFOEN (1U << 0U)
#define USART_FCR_RX_RST (1U << 1U)
#define USART_FCR_TX_RST (1U << 2U)
#define USART_FCR_RXTL_POS (6U)
#define USART_FCR_RXTL_1B (0x0 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_4B (0x1 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_8B (0x2 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_14B (0x3 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_MASK (0x3 << USART_FCR_RXTL_POS)
#define USART_LCR_WLS_POS (0U)
#define USART_LCR_WLS_5B (0x0U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_6B (0x1U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_7B (0x2U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_8B (0x3U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_MASK (0x3U << USART_LCR_WLS_POS)
#define USART_LCR_SBS_POS (2U)
#define USART_LCR_SBS_1B (0U << USART_LCR_SBS_POS)
#define USART_LCR_SBS_2B (0U << USART_LCR_SBS_POS)
#define USART_LCR_SBS_MASK (0x1 << USART_LCR_SBS_POS)
#define USART_LCR_PE (1U << 3U)
#define USART_LCR_PS_POS (4U)
#define USART_LCR_PS_ODD (0x0U << USART_LCR_PS_POS)
#define USART_LCR_PS_EVEN (0x1U << USART_LCR_PS_POS)
#define USART_LCR_PS_F1 (0x2U << USART_LCR_PS_POS)
#define USART_LCR_PS_F0 (0x3U << USART_LCR_PS_POS)
#define USART_LCR_PS_MASK (0x3U << USART_LCR_PS_POS)
#define USART_LCR_DLAB (1U << 7U)
#define USART_LSR_RDR (1U << 0U)
#define USART_LSR_THRE (1U << 5U)
#define USART_TER_TXEN (1U << 7U)
#define USART_IER_RBRINTEN (1U << 0U) // Rx Has Data
#define USART_IER_THRINTEN (1U << 1U) // Tx Empty
// ------------------------------------------------------------------------------------------------
// ----- Timer -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x 32-bitcounter/timers CT32B0/1 Modification date=3/16/2011 Major revision=0 Minor revision=3
*/
typedef struct { /*!< (@ 0x40014000) CT32B0 Structure */
__IO uint32_t IR; /*!< (@ 0x40014000) Interrupt Register */
__IO uint32_t TCR; /*!< (@ 0x40014004) Timer Control Register */
__IO uint32_t TC; /*!< (@ 0x40014008) Timer Counter */
__IO uint32_t PR; /*!< (@ 0x4001400C) Prescale Register */
__IO uint32_t PC; /*!< (@ 0x40014010) Prescale Counter */
__IO uint32_t MCR; /*!< (@ 0x40014014) Match Control Register */
union {
__IO uint32_t MR[4]; /*!< (@ 0x40014018) Match Register */
struct{
__IO uint32_t MR0; /*!< (@ 0x40018018) Match Register. MR0 */
__IO uint32_t MR1; /*!< (@ 0x4001801C) Match Register. MR1 */
__IO uint32_t MR2; /*!< (@ 0x40018020) Match Register. MR2 */
__IO uint32_t MR3; /*!< (@ 0x40018024) Match Register. MR3 */
};
};
__IO uint32_t CCR; /*!< (@ 0x40014028) Capture Control Register */
union{
__I uint32_t CR[4]; /*!< (@ 0x4001402C) Capture Register */
struct{
__I uint32_t CR0; /*!< (@ 0x4001802C) Capture Register. CR 0 */
__I uint32_t CR1; /*!< (@ 0x40018030) Capture Register. CR 1 */
__I uint32_t CR2; /*!< (@ 0x40018034) Capture Register. CR 2 */
__I uint32_t CR3; /*!< (@ 0x40018038) Capture Register. CR 3 */
};
};
__IO uint32_t EMR; /*!< (@ 0x4001403C) External Match Register */
__I uint32_t RESERVED0[12];
__IO uint32_t CTCR; /*!< (@ 0x40014070) Count Control Register */
__IO uint32_t PWMC; /*!< (@ 0x40014074) PWM Control Register */
} LPC_CTxxBx_Type;
// ------------------------------------------------------------------------------------------------
// ----- ADC -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x ADC Modification date=3/16/2011 Major revision=0 Minor revision=3 (ADC)
*/
typedef struct { /*!< (@ 0x4001C000) ADC Structure */
__IO uint32_t CR; /*!< (@ 0x4001C000) A/D Control Register */
__IO uint32_t GDR; /*!< (@ 0x4001C004) A/D Global Data Register */
__I uint32_t RESERVED0[1];
__IO uint32_t INTEN; /*!< (@ 0x4001C00C) A/D Interrupt Enable Register */
union{
__I uint32_t DR[8]; /*!< (@ 0x4001C010) A/D Channel Data Register*/
struct{
__IO uint32_t DR0; /*!< (@ 0x40020010) A/D Channel Data Register 0*/
__IO uint32_t DR1; /*!< (@ 0x40020014) A/D Channel Data Register 1*/
__IO uint32_t DR2; /*!< (@ 0x40020018) A/D Channel Data Register 2*/
__IO uint32_t DR3; /*!< (@ 0x4002001C) A/D Channel Data Register 3*/
__IO uint32_t DR4; /*!< (@ 0x40020020) A/D Channel Data Register 4*/
__IO uint32_t DR5; /*!< (@ 0x40020024) A/D Channel Data Register 5*/
__IO uint32_t DR6; /*!< (@ 0x40020028) A/D Channel Data Register 6*/
__IO uint32_t DR7; /*!< (@ 0x4002002C) A/D Channel Data Register 7*/
};
};
__I uint32_t STAT; /*!< (@ 0x4001C030) A/D Status Register. */
} LPC_ADC_Type;
// ------------------------------------------------------------------------------------------------
// ----- PMU -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x Power Management Unit (PMU) Modification date=3/16/2011 Major revision=0 Minor revision=3 (PMU)
*/
typedef struct { /*!< (@ 0x40038000) PMU Structure */
__IO uint32_t PCON; /*!< (@ 0x40038000) Power control register */
union{
__IO uint32_t GPREG[4]; /*!< (@ 0x40038004) General purpose register 0 */
struct{
__IO uint32_t GPREG0; /*!< (@ 0x40038004) General purpose register 0 */
__IO uint32_t GPREG1; /*!< (@ 0x40038008) General purpose register 1 */
__IO uint32_t GPREG2; /*!< (@ 0x4003800C) General purpose register 2 */
__IO uint32_t GPREG3; /*!< (@ 0x40038010) General purpose register 3 */
};
};
} LPC_PMU_Type;
// ------------------------------------------------------------------------------------------------
// ----- FLASHCTRL -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x Flash programming firmware Modification date=3/17/2011 Major revision=0 Minor revision=3 (FLASHCTRL)
*/
typedef struct { /*!< (@ 0x4003C000) FLASHCTRL Structure */
__I uint32_t RESERVED0[4];
__IO uint32_t FLASHCFG; /*!< (@ 0x4003C010) Flash memory access time configuration register */
__I uint32_t RESERVED1[3];
__IO uint32_t FMSSTART; /*!< (@ 0x4003C020) Signature start address register */
__IO uint32_t FMSSTOP; /*!< (@ 0x4003C024) Signature stop-address register */
__I uint32_t RESERVED2[1];
__I uint32_t FMSW0; /*!< (@ 0x4003C02C) Word 0 [31:0] */
__I uint32_t FMSW1; /*!< (@ 0x4003C030) Word 1 [63:32] */
__I uint32_t FMSW2; /*!< (@ 0x4003C034) Word 2 [95:64] */
__I uint32_t FMSW3; /*!< (@ 0x4003C038) Word 3 [127:96] */
__I uint32_t RESERVED3[1001];
__I uint32_t FMSTAT; /*!< (@ 0x4003CFE0) Signature generation status register */
__I uint32_t RESERVED4[1];
__IO uint32_t FMSTATCLR; /*!< (@ 0x4003CFE8) Signature generation status clear register */
} LPC_FLASHCTRL_Type;
// ------------------------------------------------------------------------------------------------
// ----- SSP0/1 -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x SSP/SPI Modification date=3/16/2011 Major revision=0 Minor revision=3 (SSP0)
*/
typedef struct { /*!< (@ 0x40040000) SSP0 Structure */
__IO uint32_t CR0; /*!< (@ 0x40040000) Control Register 0. Selects the serial clock rate, bus type, and data size. */
__IO uint32_t CR1; /*!< (@ 0x40040004) Control Register 1. Selects master/slave and other modes. */
__IO uint32_t DR; /*!< (@ 0x40040008) Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */
__I uint32_t SR; /*!< (@ 0x4004000C) Status Register */
__IO uint32_t CPSR; /*!< (@ 0x40040010) Clock Prescale Register */
__IO uint32_t IMSC; /*!< (@ 0x40040014) Interrupt Mask Set and Clear Register */
__I uint32_t RIS; /*!< (@ 0x40040018) Raw Interrupt Status Register */
__I uint32_t MIS; /*!< (@ 0x4004001C) Masked Interrupt Status Register */
__IO uint32_t ICR; /*!< (@ 0x40040020) SSPICR Interrupt Clear Register */
} LPC_SSPx_Type;
#define SSP_CR0_DSS_POS (0U)
#define SSP_CR0_DSS_MASK (0xF << SSP_CR0_DSS_POS)
#define SSP_CR0_DSS(X) (((X) << SSP_CR0_DSS_POS) & SSP_CR0_DSS_MASK)
#define SSP_CR0_FRF_POS (4U)
#define SSP_CR0_FRF_MASK (0x3 << SSP_CR0_FRF_POS)
#define SSP_CR0_SCR_POS (8U)
#define SSP_CR0_SCR_MASK (0xFF << SSP_CR0_SCR_POS)
#define SSP_CR0_SCR(X) (((X) << SSP_CR0_SCR_POS) & SSP_CR0_SCR_MASK)
#define SSP_CR0_CPOL (1U << 6U)
#define SSP_CR0_CPHA (1U << 7U)
#define SSP_CR1_SPI_EN (1U << 1U)
#define SSP_CR1_SLAVE (1U << 2U)
#define SSP_CR1_SLAVE_OUTPUT_DISABLE (1U << 3U)
#define SSP_SR_TxEmpty (1U << 0U) // Tx Empty
#define SSP_SR_TxNotFull (1U << 1U)
#define SSP_SR_RxNotEmpty (1U << 2U)
#define SSP_SR_RxFull (1U << 3U)
#define SSP_SR_BUSY (1U << 4U)
#define SSP_INT_ROR (1U << 0U) // RxOverrun
#define SSP_INT_RTMIS (1U << 1U) // Rx FIFO not Empty Timeout
#define SSP_INT_RXMIS (1U << 2U) // Rx Half Full
#define SSP_INT_TXMIS (1U << 3U) // Tx Half Empty
// ------------------------------------------------------------------------------------------------
// ----- IOCONFIG -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x I/O configuration Modification date=3/16/2011 Major revision=0 Minor revision=3 (IOCONFIG)
*/
typedef struct { /*!< (@ 0x40044000) IOCONFIG Structure */
__IO uint32_t RESET_PIO0_0; /*!< (@ 0x40044000) I/O configuration for pin RESET/PIO0_0 */
__IO uint32_t PIO0_1; /*!< (@ 0x40044004) I/O configuration for pin PIO0_1/CLKOUT/CT32B0_MAT2/USB_FTOGGLE */
__IO uint32_t PIO0_2; /*!< (@ 0x40044008) I/O configuration for pin PIO0_2/SSEL0/CT16B0_CAP0 */
__IO uint32_t PIO0_3; /*!< (@ 0x4004400C) I/O configuration for pin PIO0_3/USB_VBUS */
__IO uint32_t PIO0_4; /*!< (@ 0x40044010) I/O configuration for pin PIO0_4/SCL */
__IO uint32_t PIO0_5; /*!< (@ 0x40044014) I/O configuration for pin PIO0_5/SDA */
__IO uint32_t PIO0_6; /*!< (@ 0x40044018) I/O configuration for pin PIO0_6/USB_CONNECT/SCK0 */
__IO uint32_t PIO0_7; /*!< (@ 0x4004401C) I/O configuration for pin PIO0_7/CTS */
__IO uint32_t PIO0_8; /*!< (@ 0x40044020) I/O configuration for pin PIO0_8/MISO0/CT16B0_MAT0 */
__IO uint32_t PIO0_9; /*!< (@ 0x40044024) I/O configuration for pin PIO0_9/MOSI0/CT16B0_MAT1 */
__IO uint32_t SWCLK_PIO0_10; /*!< (@ 0x40044028) I/O configuration for pin SWCLK/PIO0_10/ SCK0/CT16B0_MAT2 */
__IO uint32_t TDI_PIO0_11; /*!< (@ 0x4004402C) I/O configuration for pin TDI/PIO0_11/AD0/CT32B0_MAT3 */
__IO uint32_t TMS_PIO0_12; /*!< (@ 0x40044030) I/O configuration for pin TMS/PIO0_12/AD1/CT32B1_CAP0 */
__IO uint32_t TDO_PIO0_13; /*!< (@ 0x40044034) I/O configuration for pin TDO/PIO0_13/AD2/CT32B1_MAT0 */
__IO uint32_t TRST_PIO0_14; /*!< (@ 0x40044038) I/O configuration for pin TRST/PIO0_14/AD3/CT32B1_MAT1 */
__IO uint32_t SWDIO_PIO0_15; /*!< (@ 0x4004403C) I/O configuration for pin SWDIO/PIO0_15/AD4/CT32B1_MAT2 */
__IO uint32_t PIO0_16; /*!< (@ 0x40044040) I/O configuration for pin PIO0_16/AD5/CT32B1_MAT3/ WAKEUP */
__IO uint32_t PIO0_17; /*!< (@ 0x40044044) I/O configuration for pin PIO0_17/RTS/CT32B0_CAP0/SCLK */
__IO uint32_t PIO0_18; /*!< (@ 0x40044048) I/O configuration for pin PIO0_18/RXD/CT32B0_MAT0 */
__IO uint32_t PIO0_19; /*!< (@ 0x4004404C) I/O configuration for pin PIO0_19/TXD/CT32B0_MAT1 */
__IO uint32_t PIO0_20; /*!< (@ 0x40044050) I/O configuration for pin PIO0_20/CT16B1_CAP0 */
__IO uint32_t PIO0_21; /*!< (@ 0x40044054) I/O configuration for pin PIO0_21/CT16B1_MAT0/MOSI1 */
__IO uint32_t PIO0_22; /*!< (@ 0x40044058) I/O configuration for pin PIO0_22/AD6/CT16B1_MAT1/MISO1 */
__IO uint32_t PIO0_23; /*!< (@ 0x4004405C) I/O configuration for pin PIO0_23/AD7 */
__IO uint32_t PIO1_0; /*!< Offset: 0x060 */
__IO uint32_t PIO1_1;
__IO uint32_t PIO1_2;
__IO uint32_t PIO1_3;
__IO uint32_t PIO1_4; /*!< Offset: 0x070 */
__IO uint32_t PIO1_5; /*!< (@ 0x40044074) I/O configuration for pin PIO1_5/CT32B1_CAP1 */
__IO uint32_t PIO1_6;
__IO uint32_t PIO1_7;
__IO uint32_t PIO1_8; /*!< Offset: 0x080 */
__IO uint32_t PIO1_9;
__IO uint32_t PIO1_10;
__IO uint32_t PIO1_11;
__IO uint32_t PIO1_12; /*!< Offset: 0x090 */
__IO uint32_t PIO1_13; /*!< (@ 0x40044094) I/O configuration for pin PIO1_13/DTR/CT16B0_MAT0/TXD */
__IO uint32_t PIO1_14; /*!< (@ 0x40044098) I/O configuration for pin PIO1_14/DSR/CT16B0_MAT1/RXD */
__IO uint32_t PIO1_15; /*!< (@ 0x4004409C) I/O configuration for pin PIO1_15/DCD/ CT16B0_MAT2/SCK1 */
__IO uint32_t PIO1_16; /*!< (@ 0x400440A0) I/O configuration for pin PIO1_16/RI/CT16B0_CAP0 */
__IO uint32_t PIO1_17;
__IO uint32_t PIO1_18;
__IO uint32_t PIO1_19; /*!< (@ 0x400440AC) I/O configuration for pin PIO1_19/DTR/SSEL1 */
__IO uint32_t PIO1_20; /*!< (@ 0x400440B0) I/O configuration for pin PIO1_20/DSR/SCK1 */
__IO uint32_t PIO1_21; /*!< (@ 0x400440B4) I/O configuration for pin PIO1_21/DCD/MISO1 */
__IO uint32_t PIO1_22; /*!< (@ 0x400440B8) I/O configuration for pin PIO1_22/RI/MOSI1 */
__IO uint32_t PIO1_23; /*!< (@ 0x400440BC) I/O configuration for pin PIO1_23/CT16B1_MAT1/SSEL1 */
__IO uint32_t PIO1_24; /*!< (@ 0x400440C0) I/O configuration for pin PIO1_24/ CT32B0_MAT0 */
__IO uint32_t PIO1_25; /*!< (@ 0x400440C4) I/O configuration for pin PIO1_25/CT32B0_MAT1 */
__IO uint32_t PIO1_26; /*!< (@ 0x400440C8) I/O configuration for pin PIO1_26/CT32B0_MAT2/ RXD */
__IO uint32_t PIO1_27; /*!< (@ 0x400440CC) I/O configuration for pin PIO1_27/CT32B0_MAT3/ TXD */
__IO uint32_t PIO1_28; /*!< (@ 0x400440D0) I/O configuration for pin PIO1_28/CT32B0_CAP0/ SCLK */
__IO uint32_t PIO1_29; /*!< (@ 0x400440D4) I/O configuration for pin PIO1_29/SCK0/ CT32B0_CAP1 */
__IO uint32_t PIO1_30;
__IO uint32_t PIO1_31; /*!< (@ 0x400440DC) I/O configuration for pin PIO1_31 */
} LPC_IOCON_Type;
// ------------------------------------------------------------------------------------------------
// ----- SYSCON -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x System control block Modification date=3/16/2011 Major revision=0 Minor revision=3 (SYSCON)
*/
typedef struct { /*!< (@ 0x40048000) SYSCON Structure */
__IO uint32_t SYSMEMREMAP; /*!< (@ 0x40048000) System memory remap */
__IO uint32_t PRESETCTRL; /*!< (@ 0x40048004) Peripheral reset control */
__IO uint32_t SYSPLLCTRL; /*!< (@ 0x40048008) System PLL control */
__I uint32_t SYSPLLSTAT; /*!< (@ 0x4004800C) System PLL status */
__IO uint32_t USBPLLCTRL; /*!< (@ 0x40048010) USB PLL control */
__I uint32_t USBPLLSTAT; /*!< (@ 0x40048014) USB PLL status */
__I uint32_t RESERVED0[2];
__IO uint32_t SYSOSCCTRL; /*!< (@ 0x40048020) System oscillator control */
__IO uint32_t WDTOSCCTRL; /*!< (@ 0x40048024) Watchdog oscillator control */
__I uint32_t RESERVED1[2];
__IO uint32_t SYSRSTSTAT; /*!< (@ 0x40048030) System reset status register */
__I uint32_t RESERVED2[3];
__IO uint32_t SYSPLLCLKSEL; /*!< (@ 0x40048040) System PLL clock source select */
__IO uint32_t SYSPLLCLKUEN; /*!< (@ 0x40048044) System PLL clock source update enable */
__IO uint32_t USBPLLCLKSEL; /*!< (@ 0x40048048) USB PLL clock source select */
__IO uint32_t USBPLLCLKUEN; /*!< (@ 0x4004804C) USB PLL clock source update enable */
__I uint32_t RESERVED3[8];
__IO uint32_t MAINCLKSEL; /*!< (@ 0x40048070) Main clock source select */
__IO uint32_t MAINCLKUEN; /*!< (@ 0x40048074) Main clock source update enable */
__IO uint32_t SYSAHBCLKDIV; /*!< (@ 0x40048078) System clock divider */
__I uint32_t RESERVED4[1];
__IO uint32_t SYSAHBCLKCTRL; /*!< (@ 0x40048080) System clock control */
__I uint32_t RESERVED5[4];
__IO uint32_t SSP0CLKDIV; /*!< (@ 0x40048094) SSP0 clock divider */
__IO uint32_t UARTCLKDIV; /*!< (@ 0x40048098) UART clock divider */
__IO uint32_t SSP1CLKDIV; /*!< (@ 0x4004809C) SSP1 clock divider */
__I uint32_t RESERVED6[8];
__IO uint32_t USBCLKSEL; /*!< (@ 0x400480C0) USB clock source select */
__IO uint32_t USBCLKUEN; /*!< (@ 0x400480C4) USB clock source update enable */
__IO uint32_t USBCLKDIV; /*!< (@ 0x400480C8) USB clock source divider */
__I uint32_t RESERVED7[5];
__IO uint32_t CLKOUTSEL; /*!< (@ 0x400480E0) CLKOUT clock source select */
__IO uint32_t CLKOUTUEN; /*!< (@ 0x400480E4) CLKOUT clock source update enable */
__IO uint32_t CLKOUTDIV; /*!< (@ 0x400480E8) CLKOUT clock divider */
__I uint32_t RESERVED8[5];
__I uint32_t PIOPORCAP0; /*!< (@ 0x40048100) POR captured PIO status 0 */
__I uint32_t PIOPORCAP1; /*!< (@ 0x40048104) POR captured PIO status 1 */
__I uint32_t RESERVED9[18];
__IO uint32_t BODCTRL; /*!< (@ 0x40048150) Brown-Out Detect */
__IO uint32_t SYSTCKCAL; /*!< (@ 0x40048154) System tick counter calibration */
__I uint32_t RESERVED10[6];
__IO uint32_t IRQLATENCY; /*!< (@ 0x40048170) IQR delay */
__IO uint32_t NMISRC; /*!< (@ 0x40048174) NMI Source Control */
__IO uint32_t PINTSEL[8]; /*!< (@ 0x40048178) GPIO Pin Interrupt Select register 0 */
__IO uint32_t USBCLKCTRL; /*!< (@ 0x40048198) USB clock control */
__I uint32_t USBCLKST; /*!< (@ 0x4004819C) USB clock status */
__I uint32_t RESERVED11[25];
__IO uint32_t STARTERP0; /*!< (@ 0x40048204) Start logic 0 interrupt wake-up enable register 0 */
__I uint32_t RESERVED12[3];
__IO uint32_t STARTERP1; /*!< (@ 0x40048214) Start logic 1 interrupt wake-up enable register 1 */
__I uint32_t RESERVED13[6];
__IO uint32_t PDSLEEPCFG; /*!< (@ 0x40048230) Power-down states in deep-sleep mode */
__IO uint32_t PDAWAKECFG; /*!< (@ 0x40048234) Power-down states for wake-up from deep-sleep */
__IO uint32_t PDRUNCFG; /*!< (@ 0x40048238) Power configuration register */
__I uint32_t RESERVED14[110];
__I uint32_t DEVICE_ID; /*!< (@ 0x400483F4) Device ID */
} LPC_SYSCON_Type;
#define SYSCON_PRESETCTRL_SSP0_RSTn (1U << 0U)
#define SYSCON_PRESETCTRL_I2C_RSTn (1U << 1U)
#define SYSCON_PRESETCTRL_SSP1_RSTn (1U << 2U)
// SYSCON_SYSPLLCTRL
#define SYSCON_SYSPLLCTRL_MSEL_POS (0U)
#define SYSCON_SYSPLLCTRL_MSEL_MASK (0x1FU << SYSPLLCTRL_MSEL_POS)
#define SYSCON_SYSPLLCTRL_PSEL_POS (5U)
#define SYSCON_SYSPLLCTRL_PSEL_MASK (0x03U << SYSPLLCTRL_PSEL_POS)
// SYSCON_SYSPLLSTAT
#define SYSCON_SYSPLLSTAT_LOCK 0x1U
// SYSCON_SYSPLLCLKSEL
#define SYSCON_SYSPLLCLKSEL_IRC (0x00U << 0)
#define SYSCON_SYSPLLCLKSEL_SYSOSC (0x01U << 0)
#define SYSCON_SYSPLLCLKUEN_ENA 0x01U
#define SYSCON_USBPLLCLKSEL_IRC (0U << 0U)
#define SYSCON_USBPLLCLKSEL_SYSOSC (1U << 0U)
#define SYSCON_USBPLLCLKUEN_ENA 0x01U
#define SYSCON_MAINCLKSEL_IRC (0x00U << 0)
#define SYSCON_MAINCLKSEL_PLLIN (0x01U << 0)
#define SYSCON_MAINCLKSEL_WATCHDOG (0x02U << 0)
#define SYSCON_MAINCLKSEL_PLLOUT (0x03U << 0)
#define SYSCON_MAINCLKUEN_ENA 0x01U
#define SYSCON_SYSAHBCLKCTRL_SYS (1U << 0)
#define SYSCON_SYSAHBCLKCTRL_ROM (1U << 1)
#define SYSCON_SYSAHBCLKCTRL_RAM0 (1U << 2)
#define SYSCON_SYSAHBCLKCTRL_FLASHREG (1U << 3)
#define SYSCON_SYSAHBCLKCTRL_FLASHARRAY (1U << 4)
#define SYSCON_SYSAHBCLKCTRL_I2C (1U << 5)
#define SYSCON_SYSAHBCLKCTRL_GPIO (1U << 6)
#define SYSCON_SYSAHBCLKCTRL_CT16B0 (1U << 7)
#define SYSCON_SYSAHBCLKCTRL_CT16B1 (1U << 8)
#define SYSCON_SYSAHBCLKCTRL_CT32B0 (1U << 9)
#define SYSCON_SYSAHBCLKCTRL_CT32B1 (1U << 10)
#define SYSCON_SYSAHBCLKCTRL_SSP0 (1U << 11)
#define SYSCON_SYSAHBCLKCTRL_USART (1U << 12)
#define SYSCON_SYSAHBCLKCTRL_ADC (1U << 13)
#define SYSCON_SYSAHBCLKCTRL_USB (1U << 14)
#define SYSCON_SYSAHBCLKCTRL_WWDT (1U << 15)
#define SYSCON_SYSAHBCLKCTRL_IOCON (1U << 16)
#define SYSCON_SYSAHBCLKCTRL_SSP1 (1U << 18)
#define SYSCON_SYSAHBCLKCTRL_PINT (1U << 19)
#define SYSCON_SYSAHBCLKCTRL_GROUP0INT (1U << 23)
#define SYSCON_SYSAHBCLKCTRL_GROUP1INT (1U << 24)
#define SYSCON_SYSAHBCLKCTRL_RAM1 (1U << 26)
#define SYSCON_SYSAHBCLKCTRL_USBRAM (1U << 27)
#define SYSCON_USBCLKSEL_USBPLLOUT (0U << 0U)
#define SYSCON_USBCLKSEL_MAINCLK (1U << 0U)
#define SYSCON_USBCLKUEN_ENA 0x01U
#define SYSCON_USBCLKDIV_MASK
#define SYSCON_PDRUNCFG_IRCOUT_PD (1U << 0U)
#define SYSCON_PDRUNCFG_IRC_PD (1U << 1U)
#define SYSCON_PDRUNCFG_FLASH_PD (1U << 2U)
#define SYSCON_PDRUNCFG_BOD_PD (1U << 3U)
#define SYSCON_PDRUNCFG_ADC_PD (1U << 4U)
#define SYSCON_PDRUNCFG_SYSSOC_PD (1U << 5U)
#define SYSCON_PDRUNCFG_WDTOSC_PD (1U << 6U)
#define SYSCON_PDRUNCFG_SYSPLL_PD (1U << 7U)
#define SYSCON_PDRUNCFG_USBPLL_PD (1U << 8U)
#define SYSCON_PDRUNCFG_USBPAD_PD (1U << 10U)
// ------------------------------------------------------------------------------------------------
// ----- GPIO_PIN_INT -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PIN_INT)
*/
typedef struct { /*!< (@ 0x4004C000) GPIO_PIN_INT Structure */
__IO uint32_t ISEL; /*!< (@ 0x4004C000) Pin Interrupt Mode register */
__IO uint32_t IENR; /*!< (@ 0x4004C004) Pin Interrupt Enable (Rising) register */
__IO uint32_t SIENR; /*!< (@ 0x4004C008) Set Pin Interrupt Enable (Rising) register */
__IO uint32_t CIENR; /*!< (@ 0x4004C00C) Clear Pin Interrupt Enable (Rising) register */
__IO uint32_t IENF; /*!< (@ 0x4004C010) Pin Interrupt Enable Falling Edge / Active Level register */
__IO uint32_t SIENF; /*!< (@ 0x4004C014) Set Pin Interrupt Enable Falling Edge / Active Level register */
__IO uint32_t CIENF; /*!< (@ 0x4004C018) Clear Pin Interrupt Enable Falling Edge / Active Level address */
__IO uint32_t RISE; /*!< (@ 0x4004C01C) Pin Interrupt Rising Edge register */
__IO uint32_t FALL; /*!< (@ 0x4004C020) Pin Interrupt Falling Edge register */
__IO uint32_t IST; /*!< (@ 0x4004C024) Pin Interrupt Status register */
} LPC_GPIO_PIN_INT_Type;
// ------------------------------------------------------------------------------------------------
// ----- GPIO_GROUP_INT0/1 -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_GROUP_INT0)
*/
typedef struct { /*!< (@ 0x4005C000) GPIO_GROUP_INT0 Structure */
__IO uint32_t CTRL; /*!< (@ 0x4005C000) GPIO grouped interrupt control register */
__I uint32_t RESERVED0[7];
__IO uint32_t PORT_POL[2]; /*!< (@ 0x4005C020) GPIO grouped interrupt port 0 polarity register */
__I uint32_t RESERVED1[6];
__IO uint32_t PORT_ENA[2]; /*!< (@ 0x4005C040) GPIO grouped interrupt port 0/1 enable register */
} LPC_GPIO_GROUP_INTx_Type;
// ------------------------------------------------------------------------------------------------
// ----- USB -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x USB2.0device controller Modification date=3/16/2011 Major revision=0 Minor revision=3 (USB)
*/
typedef struct { /*!< (@ 0x40080000) USB Structure */
__IO uint32_t DEVCMDSTAT; /*!< (@ 0x40080000) USB Device Command/Status register */
__IO uint32_t INFO; /*!< (@ 0x40080004) USB Info register */
__IO uint32_t EPLISTSTART; /*!< (@ 0x40080008) USB EP Command/Status List start address */
__IO uint32_t DATABUFSTART; /*!< (@ 0x4008000C) USB Data buffer start address */
__IO uint32_t LPM; /*!< (@ 0x40080010) Link Power Management register */
__IO uint32_t EPSKIP; /*!< (@ 0x40080014) USB Endpoint skip */
__IO uint32_t EPINUSE; /*!< (@ 0x40080018) USB Endpoint Buffer in use */
__IO uint32_t EPBUFCFG; /*!< (@ 0x4008001C) USB Endpoint Buffer Configuration register */
__IO uint32_t INTSTAT; /*!< (@ 0x40080020) USB interrupt status register */
__IO uint32_t INTEN; /*!< (@ 0x40080024) USB interrupt enable register */
__IO uint32_t INTSETSTAT; /*!< (@ 0x40080028) USB set interrupt status register */
__IO uint32_t INTROUTING; /*!< (@ 0x4008002C) USB interrupt routing register */
__I uint32_t RESERVED0[1];
__I uint32_t EPTOGGLE; /*!< (@ 0x40080034) USB Endpoint toggle register */
} LPC_USB_Type;
#define USB_DEVCMDSTAT_DEVADDR_POS 0U
#define USB_DEVCMDSTAT_DEVADDR_MASK (0x7FU << USB_DEVCMDSTAT_DEVADDR_POS)
#define USB_DEVCMDSTAT_DEV_EN (1U << 7U)
#define USB_DEVCMDSTAT_SETUP (1U << 8U)
#define USB_DEVCMDSTAT_PLL_ON (1U << 9U)
#define USB_DEVCMDSTAT_LPM_SUP (1U << 11U)
#define USB_DEVCMDSTAT_INTONNAK_AO (1U << 12U)
#define USB_DEVCMDSTAT_INTONNAK_AI (1U << 13U)
#define USB_DEVCMDSTAT_INTONNAK_CO (1U << 14U)
#define USB_DEVCMDSTAT_INTONNAK_CI (1U << 15U)
#define USB_DEVCMDSTAT_DCON (1U << 16U)
#define USB_DEVCMDSTAT_DSUP (1U << 17U)
#define USB_DEVCMDSTAT_LPM_SUS (1U << 19U)
#define USB_DEVCMDSTAT_LPM_REWP (1U << 20U)
#define USB_DEVCMDSTAT_DCON_C (1U << 24U)
#define USB_DEVCMDSTAT_DSUS_C (1U << 25U)
#define USB_DEVCMDSTAT_DRES_C (1U << 26U)
#define USB_INFO_FRAME_NR_POS 0U
#define USB_INFO_FRAME_NR_MASK (0x7FFU << USB_INFO_FRAME_NR_POS)
#define USB_EPLISTSTART_POS (8U)
#define USB_EPLISTSTART_MASK (0xFFFFFF << USB_EPLISTSTART_POS)
#define USB_DATABUFSTART_POS (22U)
#define USB_DATABUFSTART_MASK (0x3FF << USB_DATABUFSTART_POS)
#define USB_INT_EPn_INT (1U)
#define USB_INT_EP(ep) (1U << (ep))
#define USB_INT_EP_ALL_INT (0x3FF)
#define USB_INT_FRAME_INT (1U << 30U)
#define USB_INT_DEV_INT (1U << 31U)
// ------------------------------------------------------------------------------------------------
// ----- GPIO_PORT -----
// ------------------------------------------------------------------------------------------------
/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PORT)
*/
typedef struct {
union {
struct {
__IO uint8_t B0[32]; /*!< (@ 0x50000000) Byte pin registers port 0; pins PIO0_0 to PIO0_31 */
__IO uint8_t B1[32]; /*!< (@ 0x50000020) Byte pin registers port 1 */
};
__IO uint8_t B[64]; /*!< (@ 0x50000000) Byte pin registers port 0/1 */
};
__I uint32_t RESERVED0[1008];
union {
struct {
__IO uint32_t W0[32]; /*!< (@ 0x50001000) Word pin registers port 0 */
__IO uint32_t W1[32]; /*!< (@ 0x50001080) Word pin registers port 1 */
};
__IO uint32_t W[64]; /*!< (@ 0x50001000) Word pin registers port 0/1 */
};
uint32_t RESERVED1[960];
__IO uint32_t DIR[2]; /* 0x2000 */
uint32_t RESERVED2[30];
__IO uint32_t MASK[2]; /* 0x2080 */
uint32_t RESERVED3[30];
__IO uint32_t PIN[2]; /* 0x2100 */
uint32_t RESERVED4[30];
__IO uint32_t MPIN[2]; /* 0x2180 */
uint32_t RESERVED5[30];
__IO uint32_t SET[2]; /* 0x2200 */
uint32_t RESERVED6[30];
__O uint32_t CLR[2]; /* 0x2280 */
uint32_t RESERVED7[30];
__O uint32_t NOT[2]; /* 0x2300 */
} LPC_GPIO_Type;
#if defined ( __CC_ARM )
#pragma no_anon_unions
#endif
// ------------------------------------------------------------------------------------------------
// ----- Peripheral memory map -----
// ------------------------------------------------------------------------------------------------
#define LPC_I2C_BASE (0x40000000)
#define LPC_WWDT_BASE (0x40004000)
#define LPC_USART_BASE (0x40008000)
#define LPC_CT16B0_BASE (0x4000C000)
#define LPC_CT16B1_BASE (0x40010000)
#define LPC_CT32B0_BASE (0x40014000)
#define LPC_CT32B1_BASE (0x40018000)
#define LPC_ADC_BASE (0x4001C000)
#define LPC_PMU_BASE (0x40038000)
#define LPC_FLASHCTRL_BASE (0x4003C000)
#define LPC_SSP0_BASE (0x40040000)
#define LPC_SSP1_BASE (0x40058000)
#define LPC_IOCON_BASE (0x40044000)
#define LPC_SYSCON_BASE (0x40048000)
#define LPC_GPIO_PIN_INT_BASE (0x4004C000)
#define LPC_GPIO_GROUP_INT0_BASE (0x4005C000)
#define LPC_GPIO_GROUP_INT1_BASE (0x40060000)
#define LPC_USB_BASE (0x40080000)
#define LPC_GPIO_BASE (0x50000000)
// ------------------------------------------------------------------------------------------------
// ----- Peripheral declaration -----
// ------------------------------------------------------------------------------------------------
#define LPC_I2C ((LPC_I2C_Type *) LPC_I2C_BASE)
#define LPC_WWDT ((LPC_WWDT_Type *) LPC_WWDT_BASE)
#define LPC_USART ((LPC_USART_Type *) LPC_USART_BASE)
#define LPC_CT16B0 ((LPC_CTxxBx_Type *) LPC_CT16B0_BASE)
#define LPC_CT16B1 ((LPC_CTxxBx_Type *) LPC_CT16B1_BASE)
#define LPC_CT32B0 ((LPC_CTxxBx_Type *) LPC_CT32B0_BASE)
#define LPC_CT32B1 ((LPC_CTxxBx_Type *) LPC_CT32B1_BASE)
#define LPC_ADC ((LPC_ADC_Type *) LPC_ADC_BASE)
#define LPC_PMU ((LPC_PMU_Type *) LPC_PMU_BASE)
#define LPC_FLASHCTRL ((LPC_FLASHCTRL_Type *) LPC_FLASHCTRL_BASE)
#define LPC_SSP0 ((LPC_SSPx_Type *) LPC_SSP0_BASE)
#define LPC_SSP1 ((LPC_SSPx_Type *) LPC_SSP1_BASE)
#define LPC_IOCON ((LPC_IOCON_Type *) LPC_IOCON_BASE)
#define LPC_SYSCON ((LPC_SYSCON_Type *) LPC_SYSCON_BASE)
#define LPC_GPIO_PIN_INT ((LPC_GPIO_PIN_INT_Type *) LPC_GPIO_PIN_INT_BASE)
#define LPC_GPIO_GROUP_INT0 ((LPC_GPIO_GROUP_INTx_Type*) LPC_GPIO_GROUP_INT0_BASE)
#define LPC_GPIO_GROUP_INT1 ((LPC_GPIO_GROUP_INTx_Type*) LPC_GPIO_GROUP_INT1_BASE)
#define LPC_USB ((LPC_USB_Type *) LPC_USB_BASE)
#define LPC_GPIO ((LPC_GPIO_Type *) LPC_GPIO_BASE)
/** @} */ /* End of group Device_Peripheral_Registers */
/** @} */ /* End of group (null) */
/** @} */ /* End of group LPC11Uxx */
#ifdef __cplusplus
}
#endif
#endif // __LPC11UXX_H__

View File

@ -0,0 +1,104 @@
/*
* Copyright (C) 2020 Yaotian Feng / Codetector
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* LPC11U35_401 memory setup
*/
MEMORY {
flash0 : org = 0x00000000, len = 64k
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x10000200, len = 7680
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x00000000, len = 0
ram5 : org = 0x00000000, len = 0
ram6 : org = 0x00000000, len = 0
ram7 : org = 0x00000000, len = 0
}
/* For each data/text section two region are defined, a virtual region
and a load region (_LMA suffix).*/
/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash0);
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash0);
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash0);
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash0);
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash0);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
/* RAM region to be used for Main stack. This stack accommodates the processing
of all exceptions and interrupts.*/
REGION_ALIAS("MAIN_STACK_RAM", ram0);
/* RAM region to be used for the process stack. This is the stack used by
the main() function.*/
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram0);
REGION_ALIAS("DATA_RAM_LMA", flash0);
/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram0);
/* RAM region to be used for the default heap.*/
REGION_ALIAS("HEAP_RAM", ram0);
Vector1C = (0 -
((__main_stack_end__) +
(Reset_Handler + 1) +
(NMI_Handler + 1) +
(HardFault_Handler + 1) +
(MemManage_Handler + 1) +
(BusFault_Handler + 1) +
(UsageFault_Handler + 1))
);
/* Generic rules inclusion.*/
INCLUDE rules.ld

View File

@ -0,0 +1,20 @@
# List of the ChibiOS generic LPC11Uxx startup and CMSIS files.
STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S \
$(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/vectors_lpc.S
STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld \
$(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/devices/LPC11Uxx \
$(CHIBIOS)/os/common/ext/CMSIS/include \
$(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
$(CHIBIOS_CONTRIB)/os/common/ext/CMSIS/LPC
STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld
ALLXASMSRC += $(STARTUPASM)
ALLCSRC += $(STARTUPSRC)
ALLINC += $(STARTUPINC)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
This file is part of ChibiOS.
ChibiOS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file LPC11Uxx/cmparams.h
* @brief ARM Cortex-M0 parameters for the NXP LPC11Uxx family.
*
* @defgroup ARMCMx_LPC11Uxx NXP Semi. LPC11Uxx.
* @ingroup ARMCMx_SPECIFIC
* @details This file contains the Cortex-M0 specific parameters for the
* NRF51x platform.
* @{
*/
#ifndef _CMPARAMS_H_
#define _CMPARAMS_H_
/**
* @brief Cortex core model.
*/
#define CORTEX_MODEL 0
/**
* @brief Systick unit presence.
*/
#define CORTEX_HAS_ST TRUE
/**
* @brief Floating Point unit presence.
*/
#define CORTEX_HAS_FPU FALSE
/**
* @brief Number of bits in priority masks.
*/
#define CORTEX_PRIORITY_BITS 2
/**
* @brief Number of interrupt vectors.
* @note This number does not include the 16 system vectors and must be
* rounded to a multiple of 8.
*/
#define CORTEX_NUM_VECTORS 32
#define LPC_VECTOR_CHECKSUM TRUE
/* The following code is not processed when the file is included from an
asm module.*/
#if !defined(_FROM_ASM_)
/* Including the device CMSIS header. Note, we are not using the definitions
from this header because we need this file to be usable also from
assembler source files. We verify that the info matches instead.*/
#include "LPC11Uxx.h"
#if CORTEX_MODEL != __CORTEX_M
#error "CMSIS __CORTEX_M mismatch"
#endif
#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
#error "CMSIS __NVIC_PRIO_BITS mismatch"
#endif
#endif /* !defined(_FROM_ASM_) */
#endif /* _CMPARAMS_H_ */
/** @} */

View File

@ -0,0 +1,3 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/GPIO/hal_pal_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/GPIO

View File

@ -0,0 +1,112 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_pal_lld.c
* @brief LPC11Uxx PAL subsystem low level driver source.
*
* @addtogroup PAL
* @{
*/
#include "hal.h"
#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief LPC1Uxx I/O ports configuration.
*
* @notapi
*/
void _pal_lld_init(void) {
// Enable GPIO / IOCON CLK
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_GPIO | SYSCON_SYSAHBCLKCTRL_IOCON;
}
/**
* @brief Group Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @notapi
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode) {
for (uint8_t i = 0; i < PAL_IOPORTS_WIDTH; ++i)
{
if (mask & (1U << i)) {
_pal_lld_setpadmode(port, i, mode);
}
}
}
/**
* @brief Pads mode setup.
* @details This function programs a pads with the specified mode.
*
* @param[in] port the port identifier
* @param[in] pad the pad id
* @param[in] mode the mode
*
* @notapi
*/
void _pal_lld_setpadmode(ioportid_t port, iopadid_t pad, iomode_t mode) {
while (pad > 0x1F){}
uint32_t* base = (uint32_t*)0x40044000;
if (LPC_IOPORT_NUM(port) == 1) {
base = (uint32_t*)0x40044060;
}
base[pad & 0x1F] = (mode & MODE_IOCONF_MASK);
if (mode & MODE_DIR_MASK) {
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] |= (uint32_t) 1U << pad;
} else {
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] &= ~(((uint32_t)1U) << pad);
}
}
#endif /* HAL_USE_PAL == TRUE */
/** @} */

View File

@ -0,0 +1,389 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_pal_lld.h
* @brief LPC11Uxx PAL subsystem low level driver header.
*
* @addtogroup PAL
* @{
*/
#ifndef HAL_PAL_LLD_H
#define HAL_PAL_LLD_H
#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
/* Specifies palInit() without parameter, required until all platforms will
be updated to the new style.*/
#define PAL_NEW_INIT
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @name Port related definitions
* @{
*/
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 32U
/**
* @brief Whole port mask.
* @details This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFFU)
/** @} */
/**
* @name Line handling macros
* @{
*/
/**
* @brief Forms a line identifier.
* @details A port/pad pair are encoded into an @p ioline_t type. The encoding
* of this type is platform-dependent.
*/
#define PAL_LINE(port, pad) \
((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad)))
/**
* @brief Decodes a port identifier from a line identifier.
*/
#define PAL_PORT(line) \
(((uint32_t)(line)) & 0xFFFFFF00U)
/**
* @brief Decodes a pad identifier from a line identifier.
*/
#define PAL_PAD(line) \
(((uint32_t)(line) & 0x000000FFU))
/**
* @brief Value identifying an invalid line.
*/
#define PAL_NOLINE 0U
/** @} */
/**
* @brief Generic I/O ports static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct {
} PALConfig;
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint32_t ioportmask_t;
/**
* @brief Digital I/O modes.
*/
typedef uint32_t iomode_t;
#define MODE_IOCONF_MASK 0xFFFF
#define MODE_FUNC_POS 0U
#define MODE_FUNC_MASK (0x7U << MODE_FUNC_POS)
#define MODE_FUNC_DEFAULT (0x0U << MODE_FUNC_POS)
#define MODE_FUNC_ALT1 (0x1U << MODE_FUNC_POS)
#define MODE_FUNC_ALT2 (0x2U << MODE_FUNC_POS)
#define MODE_FUNC_ALT3 (0x3U << MODE_FUNC_POS)
#define MODE_FUNC_ALT4 (0x4U << MODE_FUNC_POS)
#define MODE_FUNC_ALT5 (0x5U << MODE_FUNC_POS)
#define MODE_FUNC_ALT6 (0x6U << MODE_FUNC_POS)
#define MODE_FUNC_ALT7 (0x7U << MODE_FUNC_POS)
#define MODE_MODE_POS 3U
#define MODE_MODE_MASK (0x3U << MODE_MODE_POS)
#define MODE_MODE_INACTIVE (0x0U << MODE_MODE_POS)
#define MODE_MODE_PULL_DOWN (0x1U << MODE_MODE_POS)
#define MODE_MODE_PULL_UP (0x2U << MODE_MODE_POS)
#define MODE_MODE_REPEATER (0x3U << MODE_MODE_POS)
#define MODE_AD_POS (7U)
#define MODE_AD_MASK (1U << MODE_AD_POS)
#define MODE_AD_ANALOG (0U << MODE_AD_POS)
#define MODE_AD_DIGITAL (1U << MODE_AD_POS)
#define MODE_OD_ENABLE (1U << 10U)
#define MODE_DIR_POS 31U
#define MODE_DIR_MASK (0x1U << MODE_DIR_POS)
#define MODE_DIR_IN (0U << MODE_DIR_POS)
#define MODE_DIR_OUT (1U << MODE_DIR_POS)
/**
* @brief Type of an I/O line.
*/
typedef uint32_t ioline_t;
/**
* @brief Port Identifier.
* @details This type can be a scalar or some kind of pointer, do not make
* any assumption about it, use the provided macros when populating
* variables of this type.
*/
typedef uint32_t ioportid_t;
/**
* @brief Type of an pad identifier.
*/
typedef uint32_t iopadid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief First I/O port identifier.
* @details Low level drivers can define multiple ports, it is suggested to
* use this naming convention.
*/
#define LPC_IOPORT_ID(x) ((x) << 8U)
#define LPC_IOPORT_NUM(x) ((x) >> 8U)
#define IOPORT0 LPC_IOPORT_ID(0)
#define IOPORT1 LPC_IOPORT_ID(1)
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
*
* @notapi
*/
#define pal_lld_init() _pal_lld_init()
/**
* @brief Reads the physical I/O port states.
*
* @param[in] port port identifier
* @return The port bits.
*
* @notapi
*/
#define pal_lld_readport(port) \
(LPC_GPIO->PIN[LPC_IOPORT_NUM(port)])
/**
* @brief Reads the output latch.
* @details The purpose of this function is to read back the latched output
* value.
*
* @param[in] port port identifier
* @return The latched logical states.
*
* @notapi
*/
#define pal_lld_readlatch(port) \
(LPC_GPIO->PIN[LPC_IOPORT_NUM(port)])
/**
* @brief Writes a bits mask on a I/O port.
*
* @param[in] port port identifier
* @param[in] bits bits to be written on the specified port
*
* @notapi
*/
#define pal_lld_writeport(port, bits) \
do { \
(LPC_GPIO->PIN[LPC_IOPORT_NUM(port)]) = bits; \
} while (false)
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
* @note Programming an unknown or unsupported mode is silently ignored.
*
* @param[in] port port identifier
* @param[in] mask group mask
* @param[in] offset group bit offset within the port
* @param[in] mode group mode
*
* @notapi
*/
#define pal_lld_setgroupmode(port, mask, offset, mode) \
_pal_lld_setgroupmode(port, mask << offset, mode)
/**
* @brief Sets a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be ORed on the specified port
*
* @notapi
*/
#define pal_lld_setport(port, bits) \
do { \
(LPC_GPIO->SET[LPC_IOPORT_NUM(port)]) = bits; \
} while (false)
/**
* @brief Clears a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be cleared on the specified port
*
* @notapi
*/
#define pal_lld_clearport(port, bits) \
do { \
(LPC_GPIO->CLR[LPC_IOPORT_NUM(port)]) = bits; \
} while (false)
/**
* @brief Toggles a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be XORed on the specified port
*
* @notapi
*/
#define pal_lld_toggleport(port, bits) \
do { \
(LPC_GPIO->NOT[LPC_IOPORT_NUM(port)]) = bits; \
} while (false)
/**
* @brief Reads a logical state from an I/O pad.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @return The logical state.
* @retval PAL_LOW low logical state.
* @retval PAL_HIGH high logical state.
*
* @notapi
*/
#define pal_lld_readpad(port, pad) \
(LPC_GPIO->B[(PAL_IOPORTS_WIDTH * LPC_IOPORT_NUM(port)) + pad])
/**
* @brief Writes a logical state on an output pad.
* @note This function is not meant to be invoked directly by the
* application code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @param[in] bit logical value, the value must be @p PAL_LOW or
* @p PAL_HIGH
*
* @notapi
*/
#define pal_lld_writepad(port, pad, bit) \
do { \
(LPC_GPIO->B[(PAL_IOPORTS_WIDTH * LPC_IOPORT_NUM(port)) + pad]) = bit; \ \
} while (false)
/**
* @brief Pad mode setup.
* @details This function programs a pad with the specified mode.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
* @note Programming an unknown or unsupported mode is silently ignored.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @param[in] mode pad mode
*
* @notapi
*/
#define pal_lld_setpadmode(port, pad, mode) \
_pal_lld_setpadmode(port, pad, mode)
/**
* @brief Returns a PAL event structure associated to a pad.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_get_pad_event(port, pad) \
&_pal_events[0]; (void)(port); (void)pad
/**
* @brief Returns a PAL event structure associated to a line.
*
* @param[in] line line identifier
*
* @notapi
*/
#define pal_lld_get_line_event(line) \
&_pal_events[0]; (void)line
#if !defined(__DOXYGEN__)
#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE)
extern palevent_t _pal_events[1];
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(void);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode);
void _pal_lld_setpadmode(ioportid_t port,
iopadid_t pad,
iomode_t mode);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PAL == TRUE */
#endif /* HAL_PAL_LLD_H */
/** @} */

View File

@ -0,0 +1,3 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/SPI/hal_spi_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/SPI

View File

@ -0,0 +1,361 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_spi_lld.c
* @brief LPC11Uxx SPI subsystem low level driver source.
*
* @addtogroup SPI
* @{
*/
#include "hal.h"
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define int_enable(SSP) \
do {(SSP)->IMSC = SSP_INT_RTMIS | SSP_INT_RXMIS | SSP_INT_TXMIS; } while(0)
#define int_disable(SSP) \
do {(SSP)->IMSC = 0; } while(0)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief SPI1 driver identifier.
*/
#if (LPC_SPI_USE_SPI1 == TRUE) || defined(__DOXYGEN__)
SPIDriver SPID1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
void ssp_irq_handler_impl(SPIDriver *spip, LPC_SSPx_Type* ssp) {
while (ssp->SR & SSP_SR_RxNotEmpty){
if (spip->rxbuf) {
if (spip->config->data_size > 8) {
((uint16_t*)spip->txbuf)[spip->cnt] = (uint16_t)ssp->DR;
} else {
((uint8_t*)spip->txbuf)[spip->cnt] = (uint8_t)ssp->DR;
}
} else {
(void) ssp->DR;
}
spip->cnt++;
if (spip->cnt < spip->size) {
if (spip->txbuf) {
if (spip->config->data_size > 8) {
LPC_SSP1->DR = ((uint16_t*)spip->txbuf)[spip->cnt];
} else {
LPC_SSP1->DR = ((uint8_t*)spip->txbuf)[spip->cnt];
}
} else {
ssp->DR = 0;
}
} else {
break;
}
}
if ((ssp->SR & SSP_SR_BUSY) == 0 && spip->cnt >= spip->size) {
// Transaction Complete
int_disable(ssp);
_spi_isr_code(spip);
}
if (ssp->RIS & SSP_INT_ROR) {
ssp->ICR = SSP_INT_ROR;
}
if (ssp->RIS & SSP_INT_RTMIS) {
ssp->ICR = SSP_INT_RTMIS;
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if LPC_SPI_USE_SPI1 == TRUE
#ifndef LPC_SSP1_IRQ_VECTOR
#error "LPC_SSP1_IRQ_VECTOR not defined"
#endif
OSAL_IRQ_HANDLER(LPC_SSP1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
ssp_irq_handler_impl(&SPID1, LPC_SSP1);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level SPI driver initialization.
*
* @notapi
*/
void spi_lld_init(void) {
#if LPC_SPI_USE_SPI1 == TRUE
/* Driver initialization.*/
spiObjectInit(&SPID1);
// Enable AHBCLK
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_SSP1;
#endif
}
/**
* @brief Configures and activates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_start(SPIDriver *spip) {
if (spip->state == SPI_STOP) {
/* Enables the peripheral.*/
#if LPC_SPI_USE_SPI1 == TRUE
if (&SPID1 == spip) {
// Set Clock Divider
LPC_SYSCON->SSP1CLKDIV = (uint32_t) spip->config->clock_divider;
LPC_SYSCON->PRESETCTRL |= SYSCON_PRESETCTRL_SSP1_RSTn; // Clear Reset
LPC_SSP1->CR0 = SSP_CR0_DSS(spip->config->data_size - 1) |
SSP_CR0_SCR(spip->config->clock_rate);
LPC_SSP1->CPSR = spip->config->clock_prescaler;
int_disable(LPC_SSP1);
LPC_SSP1->CR1 = SSP_CR1_SPI_EN; // Run in Master mode
#if !defined(LPC_SPI_SPI1_IRQ_PRIORITY)
#error "LPC_SPI_SPI1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(SSP1_IRQn, LPC_SPI_SPI1_IRQ_PRIORITY);
}
#endif
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_stop(SPIDriver *spip) {
if (spip->state == SPI_READY) {
/* Disables the peripheral.*/
#if LPC_SPI_USE_SPI1 == TRUE
if (&SPID1 == spip) {
LPC_SSP1->CR1 = 0; // Disable SSP1
LPC_SYSCON->PRESETCTRL &= ~SYSCON_PRESETCTRL_SSP1_RSTn; // Reset SSP1
nvicDisableVector(SSP1_IRQn);
}
#endif
}
}
/**
* @brief Asserts the slave select signal and prepares for transfers.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_select(SPIDriver *spip) {
(void)spip;
}
/**
* @brief Deasserts the slave select signal.
* @details The previously selected peripheral is unselected.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_unselect(SPIDriver *spip) {
(void)spip;
}
/**
* @brief Ignores data on the SPI bus.
* @details This asynchronous function starts the transmission of a series of
* idle words on the SPI bus and ignores the received data.
* @post At the end of the operation the configured callback is invoked.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be ignored
*
* @notapi
*/
void spi_lld_ignore(SPIDriver *spip, size_t n) {
spi_lld_exchange(spip, n, NULL, NULL);
}
/**
* @brief Exchanges data on the SPI bus.
* @details This asynchronous function starts a simultaneous transmit/receive
* operation.
* @post At the end of the operation the configured callback is invoked.
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
* @param[out] rxbuf the pointer to the receive buffer
*
* @notapi
*/
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) {
if (n == 0) {
return;
}
spip->txbuf = txbuf;
spip->rxbuf = rxbuf;
spip->size = n;
spip->cnt = 0;
#if LPC_SPI_USE_SPI1 == TRUE
if (spip == &SPID1) {
// Wait for SPI IDLE. Empty RX buffer
while(LPC_SSP1->SR & (SSP_SR_BUSY | SSP_SR_RxNotEmpty)) {
if (LPC_SSP1->SR) {
(void)LPC_SSP1->DR;
}
}
// Enable Interrupts
LPC_SSP1->ICR = 0x3; // Clear Interrutps
int_enable(LPC_SSP1);
if (txbuf) {
if (spip->config->data_size > 8) {
LPC_SSP1->DR = ((uint16_t*)spip->txbuf)[spip->cnt];
} else {
LPC_SSP1->DR = ((uint8_t*)spip->txbuf)[spip->cnt];
}
} else {
LPC_SSP1->DR = 0;
}
}
#endif
}
/**
* @brief Sends data over the SPI bus.
* @details This asynchronous function starts a transmit operation.
* @post At the end of the operation the configured callback is invoked.
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
*/
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
spi_lld_exchange(spip, n, txbuf, NULL);
}
/**
* @brief Receives data from the SPI bus.
* @details This asynchronous function starts a receive operation.
* @post At the end of the operation the configured callback is invoked.
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to receive
* @param[out] rxbuf the pointer to the receive buffer
*
* @notapi
*/
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
spi_lld_exchange(spip, n, NULL, rxbuf);
}
#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
/**
* @brief Aborts the ongoing SPI operation, if any.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @notapi
*/
void spi_lld_abort(SPIDriver *spip) {
(void)spip;
}
#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */
/**
* @brief Exchanges one frame using a polled wait.
* @details This synchronous function exchanges one frame using a polled
* synchronization method. This function is useful when exchanging
* small amount of data on high speed channels, usually in this
* situation is much more efficient just wait for completion using
* polling than suspending the thread waiting for an interrupt.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] frame the data frame to send over the SPI bus
* @return The received data frame from the SPI bus.
*
* @notapi
*/
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
#if LPC_SPI_USE_SPI1 == TRUE
if (spip == &SPID1) {
// Wait for SPI IDLE. Empty RX buffer
while(LPC_SSP1->SR & (SSP_SR_BUSY | SSP_SR_RxNotEmpty)) {
if (LPC_SSP1->SR) {
(void)LPC_SSP1->DR;
}
}
LPC_SSP1->DR = frame;
while((LPC_SSP1->SR & SSP_SR_RxNotEmpty) != 0){} // Wait till RxNotEmpty
return (uint16_t) LPC_SSP1->DR;
}
#endif
return 0;
}
#endif /* HAL_USE_SPI == TRUE */
/** @} */

View File

@ -0,0 +1,130 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_spi_lld.h
* @brief LPC11Uxx SPI subsystem low level driver header.
*
* @addtogroup SPI
* @{
*/
#ifndef HAL_SPI_LLD_H
#define HAL_SPI_LLD_H
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Circular mode support flag.
*/
#define SPI_SUPPORTS_CIRCULAR FALSE
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name LPC11Uxx configuration options
* @{
*/
/**
* @brief SPI1 driver enable switch.
* @details If set to @p TRUE the support for SPI1 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_SPI_USE_SPI1) || defined(__DOXYGEN__)
#define LPC_SPI_USE_SPI1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (LPC_SPI_USE_SPI1 == FALSE)
#error "LPC_SPI_USE_SPI1 is not enabled"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Low level fields of the SPI driver structure.
*/
#define spi_lld_driver_fields \
/* size: expected transfer size. cnt: tranfered count. */ \
size_t size; \
size_t cnt; \
void* rxbuf; \
const void* txbuf
/**
* @brief Low level fields of the SPI configuration structure.
*/
#define spi_lld_config_fields \
/* Dummy configuration, it is not needed.*/ \
uint8_t clock_divider; \
uint8_t clock_prescaler; \
uint8_t clock_rate; \
uint8_t data_size
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_SPI_USE_SPI1 == TRUE) && !defined(__DOXYGEN__)
extern SPIDriver SPID1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void spi_lld_init(void);
void spi_lld_start(SPIDriver *spip);
void spi_lld_stop(SPIDriver *spip);
#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
#endif
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
void spi_lld_ignore(SPIDriver *spip, size_t n);
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf);
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
void spi_lld_abort(SPIDriver *spip);
#endif
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SPI == TRUE */
#endif /* HAL_SPI_LLD_H */
/** @} */

View File

@ -0,0 +1,5 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/STM/hal_st_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/STM

View File

@ -0,0 +1,100 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_st_lld.c
* @brief LPC11Uxx ST subsystem low level driver source.
*
* @addtogroup ST
* @{
*/
#include "hal.h"
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__)
/**
* @brief System Timer vector.
* @details This interrupt is used for system tick in periodic mode.
*
* @isr
*/
OSAL_IRQ_HANDLER(SysTick_Handler) {
OSAL_IRQ_PROLOGUE();
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
OSAL_IRQ_EPILOGUE();
}
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ST driver initialization.
*
* @notapi
*/
void st_lld_init(void) {
#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
#ifndef LPC_SYS_FREQUENCY
#error "No LPC_SYS_FREQUENCY defined"
#endif
/* Periodic systick mode, the Cortex-Mx internal systick timer is used
in this mode.*/
SysTick->LOAD = (LPC_SYS_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_ENABLE_Msk |
SysTick_CTRL_TICKINT_Msk;
SysTick->VAL = 0;
/* IRQ enabled.*/
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, LPC_ST_IRQ_PRIORITY);
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
}
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
/** @} */

View File

@ -0,0 +1,154 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_st_lld.h
* @brief PLATFORM ST subsystem low level driver header.
* @details This header is designed to be include-able without having to
* include other files from the HAL.
*
* @addtogroup ST
* @{
*/
#ifndef HAL_ST_LLD_H
#define HAL_ST_LLD_H
#include "hal.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief SysTick timer IRQ priority.
*/
#if !defined(LPC_ST_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define LPC_ST_IRQ_PRIORITY 8
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void st_lld_init(void);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Driver inline functions. */
/*===========================================================================*/
/**
* @brief Returns the time counter value.
*
* @return The counter value.
*
* @notapi
*/
static inline systime_t st_lld_get_counter(void) {
return (systime_t) SysTick->VAL;
}
/**
* @brief Starts the alarm.
* @note Makes sure that no spurious alarms are triggered after
* this call.
*
* @param[in] abstime the time to be set for the first alarm
*
* @notapi
*/
static inline void st_lld_start_alarm(systime_t abstime) {
SysTick->LOAD = (uint32_t)abstime;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | // No External Clock
SysTick_CTRL_ENABLE_Msk |
SysTick_CTRL_TICKINT_Msk;
SysTick->VAL = 0; // Trigger reload
}
/**
* @brief Stops the alarm interrupt.
*
* @notapi
*/
static inline void st_lld_stop_alarm(void) {
SysTick->CTRL &= ~((uint32_t)0b10);
}
/**
* @brief Sets the alarm time.
*
* @param[in] abstime the time to be set for the next alarm
*
* @notapi
*/
static inline void st_lld_set_alarm(systime_t abstime) {
SysTick->VAL = (uint32_t)abstime;
}
/**
* @brief Returns the current alarm time.
*
* @return The currently set alarm time.
*
* @notapi
*/
static inline systime_t st_lld_get_alarm(void) {
return (systime_t)SysTick->LOAD;
}
/**
* @brief Determines if the alarm is active.
*
* @return The alarm status.
* @retval false if the alarm is not active.
* @retval true is the alarm is active
*
* @notapi
*/
static inline bool st_lld_is_alarm_active(void) {
return ((SysTick->CTRL & 0b10) != 0);
}
#endif /* HAL_ST_LLD_H */
/** @} */

View File

@ -0,0 +1,4 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/hal_uart_lld.c \
$(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/hal_serial_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART

View File

@ -0,0 +1,208 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_serial_lld.c
* @brief LPC11Uxx serial subsystem low level driver source.
*
* @addtogroup SERIAL
* @{
*/
#include "hal.h"
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief USART1 serial driver identifier.*/
#if (LPC_SERIAL_USE_UART1 == TRUE) || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Driver default configuration.
*/
static const SerialConfig default_config = {
9600
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void load(SerialDriver *sdp) {
if (&SD1 == sdp) {
if (LPC_USART->LSR & USART_LSR_THRE) {
msg_t b;
osalSysLock();
b = oqGetI(&sdp->oqueue);
osalSysUnlock();
if (b >= MSG_OK) {
LPC_USART->THR = b;
}
}
LPC_USART->IER |= USART_IER_THRINTEN; // Enable Tx Empty
}
}
#if LPC_SERIAL_USE_UART1 == TRUE
static void notify1(io_queue_t *qp) {
(void)qp;
load(&SD1);
}
#endif
static void serial_interrupt(SerialDriver *sdp) {
if (LPC_USART->LSR & USART_LSR_RDR) {
// Rx Pending
osalSysLockFromISR();
if (iqIsEmptyI(&sdp->iqueue)) {
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
}
osalSysUnlockFromISR();
while(LPC_USART->LSR & USART_LSR_RDR) {
osalSysLockFromISR();
if (iqPutI(&sdp->iqueue, LPC_USART->RBR) < MSG_OK) {
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
}
osalSysUnlockFromISR();
}
}
if (LPC_USART->LSR & USART_LSR_THRE) {
msg_t b;
osalSysLockFromISR();
b = oqGetI(&sdp->oqueue);
osalSysUnlockFromISR();
if (b >= MSG_OK) {
LPC_USART->THR = b;
} else {
LPC_USART->IER &= ~USART_IER_THRINTEN;
osalSysLockFromISR();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
osalSysUnlockFromISR();
}
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (LPC_SERIAL_USE_UART1 == TRUE) || defined(__DOXYGEN__)
CH_IRQ_HANDLER(LPC_UART_IRQ_VECTOR) {
CH_IRQ_PROLOGUE();
serial_interrupt(&SD1);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level serial driver initialization.
*
* @notapi
*/
void sd_lld_init(void) {
#if LPC_SERIAL_USE_UART1 == TRUE
sdObjectInit(&SD1, NULL, notify1);
LPC_SYSCON->UARTCLKDIV = LPC_UART_PCLK_DIV; // Set Proper Clock Divider
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_USART; // Enable USART Clock
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*
* @notapi
*/
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
if (config == NULL) {
config = &default_config;
}
if (sdp->state == SD_STOP) {
#if LPC_SERIAL_USE_UART1 == TRUE
if (&SD1 == sdp) {
// Disable Auto Baudrate. Not helpful
LPC_USART->ACR = 0;
LPC_USART->TER = USART_TER_TXEN;
/* Clock should be set to 16x baudrate */
uint16_t uart_div = (LPC_UART_PCLK_FREQUENCY / 16) / config->speed;
LPC_USART->LCR = USART_LCR_DLAB;
LPC_USART->DLL = (uint8_t)uart_div;
LPC_USART->DLM = (uint8_t)(uart_div >> 8);
// TODO: Support user configurable Parity and word length.
LPC_USART->LCR = USART_LCR_WLS_8B;
// FIFO Reset & Enable
LPC_USART->FCR = USART_FCR_FIFOEN | USART_FCR_TX_RST | USART_FCR_RX_RST |
USART_FCR_RXTL_1B;
#if !defined(LPC_UART_UART1_IRQ_PRIORITY)
#error "LPC_UART_UART1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(UART_IRQn, LPC_UART_UART1_IRQ_PRIORITY);
LPC_USART->IER = USART_IER_RBRINTEN;
}
#endif
}
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*
* @notapi
*/
void sd_lld_stop(SerialDriver *sdp) {
if (sdp->state == SD_READY) {
#if LPC_SERIAL_USE_UART1 == TRUE
if (&SD1 == sdp) {
nvicDisableVector(UART_IRQn);
LPC_USART->IER = 0;
}
#endif
}
}
#endif /* HAL_USE_SERIAL == TRUE */
/** @} */

View File

@ -0,0 +1,134 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_serial_lld.h
* @brief PLATFORM serial subsystem low level driver header.
*
* @addtogroup SERIAL
* @{
*/
#ifndef HAL_SERIAL_LLD_H
#define HAL_SERIAL_LLD_H
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name LPC Serial configuration options
* @{
*/
/**
* @brief UART1 driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_SERIAL_USE_UART1) || defined(__DOXYGEN__)
#define LPC_SERIAL_USE_UART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if LPC_SERIAL_USE_UART1 == TRUE
/**
* @brief UART PCLK DIVIDER setting.
* @details If this is not set, then we default to generate a PCLK as close to
* 1.8432MHz as possible. This is the standard clock to a 16550.
* The LPC UART is pretty much a 16550 if you look at the registers.
*/
#if !defined(LPC_UART_PCLK_DIV) || defined(__DOXYGEN__)
#define LPC_UART_PCLK_DIV (LPC_MAINCLK_FREQUENCY / 1843200)
#endif
#define LPC_UART_PCLK_FREQUENCY \
(LPC_MAINCLK_FREQUENCY / LPC_UART_PCLK_DIV)
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief PLATFORM Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
* @note This structure content is architecture dependent, each driver
* implementation defines its own version and the custom static
* initializers.
*/
typedef struct {
/**
* @brief Bit rate.
*/
uint32_t speed;
/* End of the mandatory fields.*/
} SerialConfig;
/**
* @brief @p SerialDriver specific data.
*/
#define _serial_driver_data \
_base_asynchronous_channel_data \
/* Driver state.*/ \
sdstate_t state; \
/* Input queue.*/ \
input_queue_t iqueue; \
/* Output queue.*/ \
output_queue_t oqueue; \
/* Input circular buffer.*/ \
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
/* Output circular buffer.*/ \
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
/* End of the mandatory fields.*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_SERIAL_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SERIAL == TRUE */
#endif /* HAL_SERIAL_LLD_H */
/** @} */

View File

@ -0,0 +1,276 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_uart_lld.c
* @brief LPC11Uxx UART subsystem low level driver source.
*
* @addtogroup UART
* @{
*/
#include "hal.h"
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief UART1 driver identifier.
*/
#if (LPC_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
UARTDriver UARTD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
#define uart_enter_rx_idle_loop(uartp) (void)uartp
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if LPC_UART_USE_UART1 == TRUE
#ifndef LPC_UART_IRQ_VECTOR
#error "LPC_UART_IRQ_VECTOR not defined"
#endif
OSAL_IRQ_HANDLER(LPC_UART_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
// UARTDriver *uartp = &UARTD1;
// // Pending Recieve
// while ((uartp->rx_cnt < uartp->rx_size) &&
// (LPC_USART->LSR & USART_LSR_RDR))
// {
// uint8_t tmp = LPC_USART->RBR;
// if (uartp->rxbuf != NULL) {
// uartp->rxbuf[uartp->rx_cnt] = tmp;
// }
// uartp->rx_cnt++;
// }
// if (uartp->rx_size > 0 && uartp->rx_cnt >= uartp->rx_size) {
// uartp->rx_cnt = 0;
// uartp->rx_size = 0;
// LPC_USART->IER &= ~USART_IER_RBRINTEN; // Disable Rx Interrupt
// _uart_rx_complete_isr_code(uartp);
// }
// // Check if a pending transimit
// while ((uartp->txbuf != NULL) && // have a buffer to Tx
// (uartp->tx_cnt < uartp->tx_size) && // More bytes needs to be sent
// (LPC_USART->LSR & USART_LSR_THRE)) // have space in buffer
// {
// LPC_USART->THR = uartp->txbuf[uartp->tx_cnt];
// uartp->tx_cnt++;
// }
// if (uartp->tx_size > 0 && uartp->tx_cnt >= uartp->tx_size) {
// uartp->tx_cnt = 0;
// uartp->tx_size = 0;
// uartp->txbuf = NULL;
// LPC_USART->IER &= ~USART_IER_THRINTEN; // Disable Tx Interrupt
// _uart_tx1_isr_code(uartp);
// }
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level UART driver initialization.
*
* @notapi
*/
void uart_lld_init(void) {
#if LPC_UART_USE_UART1 == TRUE
/* Driver initialization.*/
uartObjectInit(&UARTD1);
/* Initialize Clock */
LPC_SYSCON->UARTCLKDIV = LPC_UART_PCLK_DIV; // Set Proper Clock Divider
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_USART; // Enable USART Clock
#endif
}
/**
* @brief Configures and activates the UART peripheral.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
void uart_lld_start(UARTDriver *uartp) {
if (uartp->state == UART_STOP) {
/* Enables the peripheral.*/
#if LPC_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
// Disable Auto Baudrate. Not helpful
LPC_USART->ACR = 0;
LPC_USART->TER = USART_TER_TXEN;
/* Clock should be set to 16x baudrate */
uint16_t uart_div = (LPC_UART_PCLK_FREQUENCY / 16) / uartp->config->baudrate;
LPC_USART->LCR = USART_LCR_DLAB;
LPC_USART->DLL = (uint8_t)uart_div;
LPC_USART->DLM = (uint8_t)(uart_div >> 8);
// TODO: Support user configurable Parity and word length.
LPC_USART->LCR = USART_LCR_WLS_8B;
// FIFO Reset & Enable
LPC_USART->FCR = USART_FCR_FIFOEN | USART_FCR_TX_RST | USART_FCR_RX_RST |
USART_FCR_RXTL_1B;
#if !defined(LPC_UART_UART1_IRQ_PRIORITY)
#error "LPC_UART_UART1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(UART_IRQn, LPC_UART_UART1_IRQ_PRIORITY);
LPC_USART->IER = USART_IER_RBRINTEN;
}
#endif
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the UART peripheral.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
void uart_lld_stop(UARTDriver *uartp) {
if (uartp->state == UART_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if LPC_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
LPC_USART->IER = 0;
nvicDisableVector(UART_IRQn);
}
#endif
}
}
/**
* @brief Starts a transmission on the UART peripheral.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] n number of data frames to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
*/
void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
const uint8_t* buf = txbuf;
if (buf == NULL) {
return;
}
size_t i = 0;
while(n > 0) {
if(LPC_USART->LSR & USART_LSR_THRE) {
LPC_USART->THR = buf[i++];
n--;
}
}
}
/**
* @brief Stops any ongoing transmission.
* @note Stopping a transmission also suppresses the transmission callbacks.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @return The number of data frames not transmitted by the
* stopped transmit operation.
*
* @notapi
*/
size_t uart_lld_stop_send(UARTDriver *uartp) {
(void)uartp;
return 0;
}
/**
* @brief Starts a receive operation on the UART peripheral.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] n number of data frames to send
* @param[out] rxbuf the pointer to the receive buffer
*
* @notapi
*/
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
const uint8_t* buf = rxbuf;
if (buf == NULL) {
return;
}
size_t i = 0;
while(n > 0) {
if(LPC_USART->LSR & USART_LSR_RDR) {
buf[i++] = LPC_USART->RBR;
n--;
}
}
}
/**
* @brief Stops any ongoing receive operation.
* @note Stopping a receive operation also suppresses the receive callbacks.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @return The number of data frames not received by the
* stopped receive operation.
*
* @notapi
*/
size_t uart_lld_stop_receive(UARTDriver *uartp) {
(void)uartp;
return 0;
}
#endif /* HAL_USE_UART == TRUE */
/** @} */

View File

@ -0,0 +1,216 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_uart_lld.h
* @brief LPC11Uxx UART subsystem low level driver header.
*
* @addtogroup UART
* @{
*/
#ifndef HAL_UART_LLD_H
#define HAL_UART_LLD_H
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name LPC11Uxx configuration options
* @{
*/
/**
* @brief UART driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_UART_USE_UART1) || defined(__DOXYGEN__)
#define LPC_UART_USE_UART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/**
* @brief UART PCLK DIVIDER setting.
* @details If this is not set, then we default to generate a PCLK as close to
* 1.8432MHz as possible. This is the standard clock to a 16550.
* The LPC UART is pretty much a 16550 if you look at the registers.
*/
#if !defined(LPC_UART_PCLK_DIV) || defined(__DOXYGEN__)
#define LPC_UART_PCLK_DIV (LPC_MAINCLK_FREQUENCY / 1843200)
#endif
#define LPC_UART_PCLK_FREQUENCY \
(LPC_MAINCLK_FREQUENCY / LPC_UART_PCLK_DIV)
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief UART driver condition flags type.
*/
typedef uint32_t uartflags_t;
/**
* @brief Type of structure representing an UART driver.
*/
typedef struct UARTDriver UARTDriver;
/**
* @brief Generic UART notification callback type.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
typedef void (*uartcb_t)(UARTDriver *uartp);
/**
* @brief Character received UART notification callback type.
*
* @param[in] uartp pointer to the @p UARTDriver object triggering the
* callback
* @param[in] c received character
*/
typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c);
/**
* @brief Receive error UART notification callback type.
*
* @param[in] uartp pointer to the @p UARTDriver object triggering the
* callback
* @param[in] e receive error mask
*/
typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
/**
* @brief Driver configuration structure.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct {
/**
* @brief End of transmission buffer callback.
*/
uartcb_t txend1_cb;
/**
* @brief Physical end of transmission callback.
*/
uartcb_t txend2_cb;
/**
* @brief Receive buffer filled callback.
*/
uartcb_t rxend_cb;
/**
* @brief Character received while out of the @p UART_RECEIVE state.
*/
uartccb_t rxchar_cb;
/**
* @brief Receive error callback.
*/
uartecb_t rxerr_cb;
/* End of the mandatory fields.*/
uint32_t baudrate;
} UARTConfig;
/**
* @brief Structure representing an UART driver.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
struct UARTDriver {
/**
* @brief Driver state.
*/
uartstate_t state;
/**
* @brief Transmitter state.
*/
uarttxstate_t txstate;
/**
* @brief Receiver state.
*/
uartrxstate_t rxstate;
/**
* @brief Current configuration data.
*/
const UARTConfig *config;
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Synchronization flag for transmit operations.
*/
bool early;
/**
* @brief Waiting thread on RX.
*/
thread_reference_t threadrx;
/**
* @brief Waiting thread on TX.
*/
thread_reference_t threadtx;
#endif /* UART_USE_WAIT */
#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
mutex_t mutex;
#endif /* UART_USE_MUTUAL_EXCLUSION */
#if defined(UART_DRIVER_EXT_FIELDS)
UART_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_UART_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver UARTD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void uart_lld_init(void);
void uart_lld_start(UARTDriver *uartp);
void uart_lld_stop(UARTDriver *uartp);
void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf);
size_t uart_lld_stop_send(UARTDriver *uartp);
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
size_t uart_lld_stop_receive(UARTDriver *uartp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_UART == TRUE */
#endif /* HAL_UART_LLD_H */
/** @} */

View File

@ -0,0 +1,5 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB/hal_usb_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB

View File

@ -0,0 +1,676 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_usb_lld.c
* @brief LPC11Uxx USB subsystem low level driver source.
*
* @addtogroup USB
* @{
*/
#include "hal.h"
#include <string.h>
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define roundup2(x, m) (((x) + (m) - 1) & ~((m) - 1))
#define LPC_USB_SRAM_START 0x20004000
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief USB- driver identifier.
*/
#if (LPC_USB_USE_USB1 == TRUE) || defined(__DOXYGEN__)
USBDriver USBD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief EP0 state.
* @note It is an union because IN and OUT endpoints are never used at the
* same time for EP0.
*/
static union {
/**
* @brief IN EP0 state.
*/
USBInEndpointState in;
/**
* @brief OUT EP0 state.
*/
USBOutEndpointState out;
} ep0_state;
/**
* @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
USB_EP_MODE_TYPE_CTRL,
_usb_ep0setup,
_usb_ep0in,
_usb_ep0out,
0x40,
0x40,
&ep0_state.in,
&ep0_state.out,
0,
NULL,
};
static struct {
uint32_t entry[20];
} *USB_EPLIST = (void*)LPC_USB_SRAM_START;
#define EPLIST_ENTRY_BUFFER_RSHIFT 6U
#define EPLIST_ENTRY_BUFFER_POS 0U
#define EPLIST_ENTRY_BUFFER_MASK (0xFFFF << EPLIST_ENTRY_BUFFER_POS)
#define EPLIST_ADDR(ADDR) \
((((uint32_t)(ADDR)) >> EPLIST_ENTRY_BUFFER_RSHIFT) & EPLIST_ENTRY_BUFFER_MASK)
#define EPLIST_ENTRY_NBYTES_POS 16U
#define EPLIST_ENTRY_NBYTES_MASK (0x3FF << EPLIST_ENTRY_NBYTES_POS)
#define EPLIST_ENTRY_NBYTES(BYTES) \
(((BYTES) << EPLIST_ENTRY_NBYTES_POS) & EPLIST_ENTRY_NBYTES_MASK)
#define EPLIST_ENTRY_ACTIVE (1U << 31U)
#define EPLIST_ENTRY_DISABLE (1U << 30U)
#define EPLIST_ENTRY_STALL (1U << 29U)
#define EPLIST_ENTRY_TOGGLE_RESET (1U << 28U)
#define EPLIST_ENTRY_RFTV (1U << 27U)
#define EPLIST_ENTRY_EPTYPE (1U << 26U)
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static size_t usb_ep_malloc(USBDriver *usbp, size_t size, size_t alignment) {
size_t current = usbp->epmem_next;
if ((current & (alignment - 1)) != 0) { // Alignment issue
current = (current + alignment) & (~(alignment - 1));
}
const size_t epmo = current;
usbp->epmem_next = current + size;
osalDbgAssert(usbp->epmem_next <= (LPC_USB_SRAM_START + 0x800), "UBSSRAM exhausted");
return epmo;
}
static void usb_packet_transmit(USBDriver *usbp, usbep_t ep, size_t n)
{
const USBEndpointConfig * const epc = usbp->epc[ep];
USBInEndpointState * const isp = epc->in_state;
if (n > epc->in_maxsize) {
n = epc->in_maxsize;
}
if (ep == 0) {
// When EP0 IN is received, set ACTIVE bit on both EP0 IN
// and OUT.
USB_EPLIST->entry[0] |= EPLIST_ENTRY_ACTIVE;
}
/* Get EP command/status List, update the length field and data pointer. */
USB_EPLIST->entry[ep * 4 + 2] &= ~0x3FFFFFF;
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_NBYTES(n) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2 + 1]);
if (n > 0)
memcpy(usbp->epn_buffer[ep*2 + 1], isp->txbuf, n);
isp->txlastpktlen = n;
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_ACTIVE;
}
static size_t usb_packet_receive(USBDriver *usbp, usbep_t ep) {
const USBEndpointConfig *epcp = usbp->epc[ep];
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
uint32_t n = (USB_EPLIST->entry[4 * ep] & EPLIST_ENTRY_NBYTES_MASK) >> EPLIST_ENTRY_NBYTES_POS;
n = epcp->out_maxsize - n;
if (osp->rxbuf != NULL && n > 0) {
memcpy(osp->rxbuf, usbp->epn_buffer[ep * 2], n);
osp->rxbuf += n;
}
// ReSetup for recieve
USB_EPLIST->entry[4 * ep] &= ~0x3FFFFFF;
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_NBYTES(epcp->out_maxsize) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]);
if (osp->rxpkts > 0)
osp->rxpkts -= 1;
osp->rxcnt += n;
osp->rxsize -= n;
return n;
}
/*===========================================================================*/
/* Driver interrupt handlers and threads. */
/*===========================================================================*/
#ifndef LPC_USB_IRQ_VECTOR
#error "LPC_USB_IRQ_VECTOR not defined"
#endif
OSAL_IRQ_HANDLER(LPC_USB_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
USBDriver *usbp = &USBD1;
uint32_t isr = LPC_USB->INTSTAT;
#define devstat (LPC_USB->DEVCMDSTAT)
LPC_USB->INTSTAT &= 0xFFFFFFFF; // Clear Flags
// SOF
if (isr & USB_INT_FRAME_INT) {
_usb_isr_invoke_sof_cb(usbp);
}
if (isr & USB_INT_DEV_INT) {
if (devstat & USB_DEVCMDSTAT_DSUS_C) {
if (devstat & USB_DEVCMDSTAT_DCON) {
if (devstat & USB_DEVCMDSTAT_DSUP) {
// Suspend
_usb_suspend(usbp);
} else {
// Wakeup
_usb_wakeup(usbp);
}
}
}
if (devstat & USB_DEVCMDSTAT_DRES_C) {
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DRES_C;
_usb_reset(usbp);
}
} // USB_INT_DEV_INT
for (int ep = 0; ep < 5; ++ep)
{
// EP0 OUT (Setup)
if (isr & (USB_INT_EPn_INT << (2 * ep))) {
if (devstat & USB_DEVCMDSTAT_SETUP) {
_usb_isr_invoke_setup_cb(usbp, ep);
} else {
// OUT endpoint, receive
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
osalSysLockFromISR();
size_t n = usb_packet_receive(usbp, ep);
osalSysUnlockFromISR();
if ((n < usbp->epc[0]->out_maxsize) || (osp->rxpkts == 0)) {
_usb_isr_invoke_out_cb(usbp, ep);
} else {
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_ACTIVE;
}
}
}
// EP0 IN
if (isr & (USB_INT_EPn_INT << (2 * ep + 1))) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
size_t n = isp->txlastpktlen;
isp->txcnt += n;
if (isp->txcnt < isp->txsize) {
isp->txbuf += n;
osalSysLockFromISR();
usb_packet_transmit(usbp, ep, isp->txsize - isp->txcnt);
osalSysUnlockFromISR();
} else {
// IN callback
_usb_isr_invoke_in_cb(usbp, ep);
}
}
}
OSAL_IRQ_EPILOGUE();
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level USB driver initialization.
*
* @notapi
*/
void usb_lld_init(void) {
#if LPC_USB_USE_USB1 == TRUE
/* Driver initialization.*/
usbObjectInit(&USBD1);
// Enable Clock
LPC_SYSCON->SYSAHBCLKCTRL |=
(
SYSCON_SYSAHBCLKCTRL_USB | SYSCON_SYSAHBCLKCTRL_USBRAM |
SYSCON_SYSAHBCLKCTRL_RAM0
);
USBD1.epmem_next = (0x50 + LPC_USB_SRAM_START);
#if defined(LPC_MAINCLK_FREQUENCY) && LPC_MAINCLK_FREQUENCY == 48000000U
// TODO: Implement proper PLL support
LPC_SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_USBPLL_PD;
LPC_SYSCON->USBPLLCLKSEL = SYSCON_USBPLLCLKSEL_SYSOSC;
LPC_SYSCON->USBPLLCLKUEN = 0;
LPC_SYSCON->USBPLLCLKUEN = SYSCON_USBPLLCLKUEN_ENA;
LPC_SYSCON->USBPLLCTRL = LPC_SYSCON->SYSPLLCTRL; // BIG HACK. Steal Main PLL CFG
while(LPC_SYSCON->USBPLLSTAT == 0){}
LPC_SYSCON->USBCLKSEL = SYSCON_USBCLKSEL_USBPLLOUT;
LPC_SYSCON->USBCLKDIV = 1; // Divide By 1
#else // LPC_MAINCLK_FREQUENCY
#error "USB Currently requires LPC_MAINCLK_FREQUENCY = 48MHz"
#endif // LPC_MAINCLK_FREQUENCY
#endif // LPC_USB_USE_USB1 == TRUE
}
/**
* @brief Configures and activates the USB peripheral.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_start(USBDriver *usbp) {
if (usbp->state == USB_STOP) {
/* Enables the peripheral.*/
#if LPC_USB_USE_USB1 == TRUE
if (&USBD1 == usbp) {
// USB Transiver Powerup
LPC_SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_USBPAD_PD;
// Enable Vector
#if !defined(LPC_USB_USB1_IRQ_PRIORITY)
#error "LPC_USB_USB1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(USB_IRQn, LPC_USB_USB1_IRQ_PRIORITY);
}
#endif
usb_lld_reset(usbp);
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the USB peripheral.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_stop(USBDriver *usbp) {
if (usbp->state == USB_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if LPC_USB_USE_USB1 == TRUE
if (&USBD1 == usbp) {
nvicDisableVector(USB_IRQn);
LPC_USB->INTEN = 0;
LPC_SYSCON->PDRUNCFG |= SYSCON_PDRUNCFG_USBPAD_PD;
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DEV_EN;
}
#endif
}
}
/**
* @brief USB low level reset routine.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_reset(USBDriver *usbp) {
/* Post reset initialization.*/
// cfg Interrupt routing to IRQ
LPC_USB->INTROUTING = 0;
LPC_USB->EPINUSE = 0;
LPC_USB->EPSKIP = 0;
LPC_USB->EPBUFCFG = 0;
// Points USB Buffers to correct places
LPC_USB->EPLISTSTART = LPC_USB_SRAM_START & USB_EPLISTSTART_MASK;
LPC_USB->DATABUFSTART = LPC_USB_SRAM_START & USB_DATABUFSTART_MASK;
// Clear Existing Interrupts
LPC_USB->INTSTAT = USB_INT_DEV_INT | USB_INT_FRAME_INT | USB_INT_EP_ALL_INT;
// Setup Interrupt Masks
LPC_USB->INTEN = USB_INT_DEV_INT | USB_INT_EP_ALL_INT;
// SOF only if there is a handler registered.
if ((usbp)->config->sof_cb != NULL) {
LPC_USB->INTEN |= USB_INT_FRAME_INT;
}
// Reset Allocator
usbp->epmem_next = (0x50 + LPC_USB_SRAM_START);
usbp->setup_buffer = NULL;
for (int i = 0; i < 10; ++i)
{
usbp->epn_buffer[i] = NULL;
}
// Disable all endpoints
for (int i = 0; i < 16; ++i)
{
USB_EPLIST->entry[i + 4] = EPLIST_ENTRY_DISABLE;
}
/* EP0 initialization.*/
usbp->epc[0] = &ep0config;
usb_lld_init_endpoint(usbp, 0);
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DEV_EN; // USB Start Running
}
/**
* @brief Sets the USB address.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_set_address(USBDriver *usbp) {
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DEVADDR_MASK;
LPC_USB->DEVCMDSTAT |= (USB_DEVCMDSTAT_DEV_EN |
(usbp->address & USB_DEVCMDSTAT_DEVADDR_MASK));
}
/**
* @brief Enables an endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
if(ep > USB_MAX_ENDPOINTS)
return;
const USBEndpointConfig *epcp = usbp->epc[ep];
uint32_t usbep_cfg = 0;
switch(epcp->ep_mode & USB_EP_MODE_TYPE) {
case USB_EP_MODE_TYPE_CTRL:
break;
case USB_EP_MODE_TYPE_ISOC:
usbep_cfg |= EPLIST_ENTRY_EPTYPE;
break;
case USB_EP_MODE_TYPE_BULK:
break;
case USB_EP_MODE_TYPE_INTR:
break;
default:
while(1) {}
}
if (epcp->out_state != NULL) {
while(epcp->out_maxsize > 1023);
uint32_t ep_mem = usb_ep_malloc(usbp, epcp->out_maxsize, 64);
usbp->epn_buffer[(2 * ep)] = (void *)ep_mem;
USB_EPLIST->entry[(4 * ep)] = usbep_cfg | EPLIST_ADDR(ep_mem)
| EPLIST_ENTRY_NBYTES(epcp->out_maxsize);
}
if (ep == 0) {
while(usbp->setup_buffer != NULL){}
// Allocate Setup Bytes
uint32_t ep_mem = usb_ep_malloc(usbp, 8, 64);
usbp->setup_buffer = (void *)ep_mem;
USB_EPLIST->entry[1] = EPLIST_ADDR(ep_mem);
LPC_USB->INTEN |= USB_INT_EP(ep * 2);
}
if (epcp->in_state != NULL) {
while(epcp->in_maxsize > 1023);
uint32_t ep_mem = usb_ep_malloc(usbp, epcp->in_maxsize, 64);
usbp->epn_buffer[(2 * ep) + 1] = (void *)ep_mem;
USB_EPLIST->entry[(4 * ep) + 2] = usbep_cfg | EPLIST_ADDR(ep_mem)
| EPLIST_ENTRY_NBYTES(epcp->in_maxsize);
LPC_USB->INTEN |= USB_INT_EP((ep * 2) + 1);
}
}
/**
* @brief Disables all the active endpoints except the endpoint zero.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_disable_endpoints(USBDriver *usbp) {
if (usbp != &USBD1)
return;
LPC_USB->EPSKIP = 0xFFFFFFFF;
LPC_USB->INTEN &= (~USB_INT_EP_ALL_INT) | USB_INT_EP(0) | USB_INT_EP(1);
while (LPC_USB->EPSKIP) {}
for (int i = 1; i < 5; ++i) // 4 EPs needs to be disabled, EP0 can't
{
USB_EPLIST->entry[i * 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 2] |= EP_STATUS_DISABLED;
USB_EPLIST->entry[i * 2 + 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 2 + 2] |= EP_STATUS_DISABLED;
}
}
/**
* @brief Returns the status of an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return The endpoint status.
* @retval EP_STATUS_DISABLED The endpoint is not active.
* @retval EP_STATUS_STALLED The endpoint is stalled.
* @retval EP_STATUS_ACTIVE The endpoint is active.
*
* @notapi
*/
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return EP_STATUS_DISABLED;
if (USB_EPLIST->entry[ep * 2] & EPLIST_ENTRY_DISABLE) {
return EP_STATUS_DISABLED;
} else if (USB_EPLIST->entry[ep * 2] & EPLIST_ENTRY_STALL) {
return EP_STATUS_STALLED;
} else {
return EP_STATUS_ACTIVE;
}
}
/**
* @brief Returns the status of an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return The endpoint status.
* @retval EP_STATUS_DISABLED The endpoint is not active.
* @retval EP_STATUS_STALLED The endpoint is stalled.
* @retval EP_STATUS_ACTIVE The endpoint is active.
*
* @notapi
*/
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return EP_STATUS_DISABLED;
if (USB_EPLIST->entry[ep * 2 + 2] & EPLIST_ENTRY_DISABLE) {
return EP_STATUS_DISABLED;
} else if (USB_EPLIST->entry[ep * 2 + 2] & EPLIST_ENTRY_STALL) {
return EP_STATUS_STALLED;
} else {
return EP_STATUS_ACTIVE;
}
}
/**
* @brief Reads a setup packet from the dedicated packet buffer.
* @details This function must be invoked in the context of the @p setup_cb
* callback in order to read the received setup packet.
* @pre In order to use this function the endpoint must have been
* initialized as a control endpoint.
* @post The endpoint is ready to accept another packet.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[out] buf buffer where to copy the packet data
*
* @notapi
*/
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
if (usbp == &USBD1) {
if (ep == 0) {
while(usbp->setup_buffer == 0){}
/* Check/Clear STALL on both EP0 IN and OUT when SETUP is received. */
USB_EPLIST->entry[0] &= ~(EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE); // EP0OUT
USB_EPLIST->entry[2] &= ~(EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE); // EP0IN
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_SETUP; // Clear SETUP
LPC_USB->DEVCMDSTAT &= ~(USB_DEVCMDSTAT_INTONNAK_CO | USB_DEVCMDSTAT_INTONNAK_CI);
memcpy(buf, usbp->setup_buffer, 8);
USB_EPLIST->entry[1] = EPLIST_ADDR(usbp->setup_buffer);
} else {
while(1){}
}
}
}
/**
* @brief Starts a receive operation on an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
const USBEndpointConfig *epcp = usbp->epc[ep];
if (osp->rxsize == 0) /* Special case for zero sized packets.*/
osp->rxpkts = 1;
else
osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
usbp->epc[ep]->out_maxsize);
USB_EPLIST->entry[ep * 4] &= ~0x3FFFFFF;
USB_EPLIST->entry[ep * 4] |= EPLIST_ENTRY_ACTIVE |
EPLIST_ENTRY_NBYTES(epcp->out_maxsize) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]);
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_INTONNAK_CO;
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_INTONNAK_CI;
}
/**
* @brief Starts a transmit operation on an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
USBInEndpointState * const isp = usbp->epc[ep]->in_state;
usb_packet_transmit(usbp, ep, isp->txsize);
}
/**
* @brief Brings an OUT endpoint in the stalled state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2);
if (USB_EPLIST->entry[ep * 4] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep*4] |= EPLIST_ENTRY_STALL;
}
/**
* @brief Brings an IN endpoint in the stalled state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2 + 1);
if (USB_EPLIST->entry[ep * 4 + 2] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_STALL;
}
/**
* @brief Brings an OUT endpoint in the active state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2);
if (USB_EPLIST->entry[ep * 4] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep*4] &= ~EPLIST_ENTRY_STALL;
}
/**
* @brief Brings an IN endpoint in the active state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2 + 1);
if (USB_EPLIST->entry[ep * 4 + 2] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep * 4 + 2] &= ~EPLIST_ENTRY_STALL;
}
#endif /* HAL_USE_USB == TRUE */
/** @} */

View File

@ -0,0 +1,408 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_usb_lld.h
* @brief LPC11Uxx USB subsystem low level driver header.
*
* @addtogroup USB
* @{
*/
#ifndef HAL_USB_LLD_H
#define HAL_USB_LLD_H
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Maximum endpoint address.
*/
#define USB_MAX_ENDPOINTS 5
/**
* @brief Status stage handling method.
*/
#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW
/**
* @brief The address can be changed immediately upon packet reception.
*/
#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS
/**
* @brief Method for set address acknowledge.
*/
#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLC11Uxx configuration options
* @{
*/
/**
* @brief USB driver enable switch.
* @details If set to @p TRUE the support for USB0 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_USB_USE_USB1) || defined(__DOXYGEN__)
#define LPC_USB_USE_USB1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of an IN endpoint state structure.
*/
typedef struct {
/**
* @brief Requested transmit transfer size.
*/
size_t txsize;
/**
* @brief Transmitted bytes so far.
*/
size_t txcnt;
/**
* @brief Pointer to the transmission linear buffer.
*/
const uint8_t *txbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
uint16_t txlastpktlen;
} USBInEndpointState;
/**
* @brief Type of an OUT endpoint state structure.
*/
typedef struct {
/**
* @brief Requested receive transfer size.
*/
size_t rxsize;
/**
* @brief Received bytes so far.
*/
size_t rxcnt;
/**
* @brief Pointer to the receive linear buffer.
*/
uint8_t *rxbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
uint16_t rxpkts;
} USBOutEndpointState;
/**
* @brief Type of an USB endpoint configuration structure.
* @note Platform specific restrictions may apply to endpoints.
*/
typedef struct {
/**
* @brief Type and mode of the endpoint.
*/
uint32_t ep_mode;
/**
* @brief Setup packet notification callback.
* @details This callback is invoked when a setup packet has been
* received.
* @post The application must immediately call @p usbReadPacket() in
* order to access the received packet.
* @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL
* endpoints, it should be set to @p NULL for other endpoint
* types.
*/
usbepcallback_t setup_cb;
/**
* @brief IN endpoint notification callback.
* @details This field must be set to @p NULL if the IN endpoint is not
* used.
*/
usbepcallback_t in_cb;
/**
* @brief OUT endpoint notification callback.
* @details This field must be set to @p NULL if the OUT endpoint is not
* used.
*/
usbepcallback_t out_cb;
/**
* @brief IN endpoint maximum packet size.
* @details This field must be set to zero if the IN endpoint is not
* used.
*/
uint16_t in_maxsize;
/**
* @brief OUT endpoint maximum packet size.
* @details This field must be set to zero if the OUT endpoint is not
* used.
*/
uint16_t out_maxsize;
/**
* @brief @p USBEndpointState associated to the IN endpoint.
* @details This structure maintains the state of the IN endpoint.
*/
USBInEndpointState *in_state;
/**
* @brief @p USBEndpointState associated to the OUT endpoint.
* @details This structure maintains the state of the OUT endpoint.
*/
USBOutEndpointState *out_state;
/* End of the mandatory fields.*/
/**
* @brief Reserved field, not currently used.
* @note Initialize this field to 1 in order to be forward compatible.
*/
uint16_t ep_buffers;
/**
* @brief Pointer to a buffer for setup packets.
* @details Setup packets require a dedicated 8-bytes buffer, set this
* field to @p NULL for non-control endpoints.
*/
uint8_t *setup_buf;
} USBEndpointConfig;
/**
* @brief Type of an USB driver configuration structure.
*/
typedef struct {
/**
* @brief USB events callback.
* @details This callback is invoked when an USB driver event is registered.
*/
usbeventcb_t event_cb;
/**
* @brief Device GET_DESCRIPTOR request callback.
* @note This callback is mandatory and cannot be set to @p NULL.
*/
usbgetdescriptor_t get_descriptor_cb;
/**
* @brief Requests hook callback.
* @details This hook allows to be notified of standard requests or to
* handle non standard requests.
*/
usbreqhandler_t requests_hook_cb;
/**
* @brief Start Of Frame callback.
*/
usbcallback_t sof_cb;
/* End of the mandatory fields.*/
} USBConfig;
/**
* @brief Structure representing an USB driver.
*/
struct USBDriver {
/**
* @brief Driver state.
*/
usbstate_t state;
/**
* @brief Current configuration data.
*/
const USBConfig *config;
/**
* @brief Bit map of the transmitting IN endpoints.
*/
uint16_t transmitting;
/**
* @brief Bit map of the receiving OUT endpoints.
*/
uint16_t receiving;
/**
* @brief Active endpoints configurations.
*/
const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1];
/**
* @brief Fields available to user, it can be used to associate an
* application-defined handler to an IN endpoint.
* @note The base index is one, the endpoint zero does not have a
* reserved element in this array.
*/
void *in_params[USB_MAX_ENDPOINTS];
/**
* @brief Fields available to user, it can be used to associate an
* application-defined handler to an OUT endpoint.
* @note The base index is one, the endpoint zero does not have a
* reserved element in this array.
*/
void *out_params[USB_MAX_ENDPOINTS];
/**
* @brief Endpoint 0 state.
*/
usbep0state_t ep0state;
/**
* @brief Next position in the buffer to be transferred through endpoint 0.
*/
uint8_t *ep0next;
/**
* @brief Number of bytes yet to be transferred through endpoint 0.
*/
size_t ep0n;
/**
* @brief Endpoint 0 end transaction callback.
*/
usbcallback_t ep0endcb;
/**
* @brief Setup packet buffer.
*/
uint8_t setup[8];
/**
* @brief Current USB device status.
*/
uint16_t status;
/**
* @brief Assigned USB address.
*/
uint8_t address;
/**
* @brief Current USB device configuration.
*/
uint8_t configuration;
/**
* @brief State of the driver when a suspend happened.
*/
usbstate_t saved_state;
#if defined(USB_DRIVER_EXT_FIELDS)
USB_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Offset of the next chunk of usb_ep_malloc
*/
size_t epmem_next;
void* setup_buffer;
void* epn_buffer[10]; // OUT = 2n, IN = 2n +1
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Returns the current frame number.
*
* @param[in] usbp pointer to the @p USBDriver object
* @return The current frame number.
*
* @notapi
*/
#define usb_lld_get_frame_number(usbp) \
((LPC_USB->INFO & USB_INFO_FRAME_NR_MASK) >> USB_INFO_FRAME_NR_POS)
/**
* @brief Returns the exact size of a receive transaction.
* @details The received size can be different from the size specified in
* @p usbStartReceiveI() because the last packet could have a size
* different from the expected one.
* @pre The OUT endpoint must have been configured in transaction mode
* in order to use this function.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return Received data size.
*
* @notapi
*/
#define usb_lld_get_transaction_size(usbp, ep) \
((usbp)->epc[ep]->out_state->rxcnt)
/**
* @brief Connects the USB device.
*
* @api
*/
#define usb_lld_connect_bus(usbp) \
(LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DCON)
/**
* @brief Disconnect the USB device.
*
* @api
*/
#define usb_lld_disconnect_bus(usbp) \
(LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DCON)
/**
* @brief Start of host wake-up procedure.
*
* @notapi
*/
#define usb_lld_wakeup_host(usbp) \
(LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DSUP)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_USB_USE_USB1 == TRUE) && !defined(__DOXYGEN__)
extern USBDriver USBD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void usb_lld_init(void);
void usb_lld_start(USBDriver *usbp);
void usb_lld_stop(USBDriver *usbp);
void usb_lld_reset(USBDriver *usbp);
void usb_lld_set_address(USBDriver *usbp);
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep);
void usb_lld_disable_endpoints(USBDriver *usbp);
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_USB == TRUE */
#endif /* HAL_USB_LLD_H */
/** @} */

View File

@ -0,0 +1,102 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_lld.c
* @brief PLATFORM HAL subsystem low level driver source.
*
* @addtogroup HAL
* @{
*/
#include "hal.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void lpc_clock_init(void) {
#if defined(LPC_USE_SYSOSC) && LPC_USE_SYSOSC != FALSE
LPC_SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSSOC_PD;
LPC_SYSCON->SYSOSCCTRL = 0;
#endif
#if LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLOUT ||\
LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLIN
// 1. Config PLL input clock
LPC_SYSCON->SYSPLLCLKSEL = LPC_SYSPLLCLKSEL;
// Switch Clock
LPC_SYSCON->SYSPLLCLKUEN = 0;
LPC_SYSCON->SYSPLLCLKUEN = SYSCON_SYSPLLCLKUEN_ENA;
#if LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLOUT
// 2. Config PLL
// Enable PLL power
LPC_SYSCON->PDRUNCFG &= (~SYSCON_PDRUNCFG_SYSPLL_PD);
// Apply PLL Config
LPC_SYSCON->SYSPLLCTRL = (LPC_SYSPLL_PSEL_VAL << SYSCON_SYSPLLCTRL_PSEL_POS)
| (LPC_SYSPLL_MSEL_VAL << SYSCON_SYSPLLCTRL_MSEL_POS);
// Wait for PLLLock
while(!(LPC_SYSCON->SYSPLLSTAT & SYSCON_SYSPLLSTAT_LOCK)){}
#endif // LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLOUT
#endif /* LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLOUT ||
LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLIN */
// Config SYSDIV
LPC_SYSCON->SYSAHBCLKDIV = LPC_SYS_DIV & 0xFF;
// Select Main Clock
LPC_SYSCON->MAINCLKSEL = LPC_MAINCLKSEL;
LPC_SYSCON->MAINCLKUEN = 0;
LPC_SYSCON->MAINCLKUEN = SYSCON_MAINCLKUEN_ENA;
}
/**
* @brief Low level HAL driver initialization.
*
* @notapi
*/
void hal_lld_init(void) {
lpc_clock_init();
}
/** @} */

View File

@ -0,0 +1,161 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file LPC11Uxx/hal_lld.h
* @brief NXP LPC 11Uxx HAL subsystem low level driver header.
*
* @addtogroup HAL
* @{
*/
#ifndef HAL_LLD_H
#define HAL_LLD_H
#include "LPC11Uxx.h"
#include "lpc_registry.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Platform identification macros
* @{
*/
#define PLATFORM_NAME "LPC"
/** @} */
/**
* @name PLATFORM configuration options
* @{
*/
#define LPC_IRC_FREQUENCY 12000000UL // 12MHz
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*
* Configuration-related checks.
*/
#if !defined(LPC11Uxx_MCUCONF) && !defined(LPC11U35_MCUCONF) && \
!defined(LPC11U35_401_MCUCONF)
#error "Using a wrong mcuconf.h file, LPC11Uxx_MCUCONF not defined"
#endif
#if defined(LPC_USE_SYSOSC) && LPC_USE_SYSOSC != FALSE && !defined(LPC_SYSOSC_FREQUENCY)
#error "LPC_SYSOSC_FREQUENCY must be defined if LPC_USE_SYSOSC"
#endif
// SYSTEMPLL SEL
#if defined(LPC_SYSPLLCLKSEL) && LPC_SYSPLLCLKSEL == SYSCON_SYSPLLCLKSEL_IRC
#define LPC_SYSPLLIN_FREQUENCY (LPC_IRC_FREQUENCY)
#elif defined(LPC_SYSPLLCLKSEL) && LPC_SYSPLLCLKSEL == SYSCON_SYSPLLCLKSEL_SYSOSC
#ifndef LPC_USE_SYSOSC
#error "LPC_USE_SYSOSC must be defined when using SYSOSC"
#endif
#define LPC_SYSPLLIN_FREQUENCY (LPC_SYSOSC_FREQUENCY)
#else
#error "LPC_SYSPLLCLKSEL must be one of SYSCON_SYSPLLCLKSEL_IRC, \
SYSCON_SYSPLLCLKSEL_SYSOSC"
#endif
#if defined(LPC_MAINCLKSEL) && LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_IRC
// Using Internal OSC
#define LPC_MAINCLK_FREQUENCY (LPC_IRC_FREQUENCY)
#elif defined(LPC_MAINCLKSEL) && LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLIN
#define LPC_MAINCLK_FREQUENCY (LPC_SYSPLLIN_FREQUENCY)
#elif defined(LPC_MAINCLKSEL) && LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_WATCHDOG
#error "Unsupported clock select"
#elif defined(LPC_MAINCLKSEL) && LPC_MAINCLKSEL == SYSCON_MAINCLKSEL_PLLOUT
// PLL OUT
#if defined(LPC_SYSPLL_MULT) && LPC_SYSPLL_MULT > 0 && LPC_SYSPLL_MULT <= 32 \
&& defined(LPC_SYSPLL_PDIV) && (LPC_SYSPLL_PDIV == 2 || LPC_SYSPLL_PDIV == 4 \
|| LPC_SYSPLL_PDIV == 8 || LPC_SYSPLL_PDIV == 16)
#if LPC_SYSPLL_PDIV == 2
#define LPC_SYSPLL_PSEL_VAL 0x0U
#elif LPC_SYSPLL_PDIV == 4
#define LPC_SYSPLL_PSEL_VAL 0x1U
#elif LPC_SYSPLL_PDIV == 8
#define LPC_SYSPLL_PSEL_VAL 0x2U
#elif LPC_SYSPLL_PDIV == 16
#define LPC_SYSPLL_PSEL_VAL 0x3U
#else
#error "INVALID PDIV VALUE"
#endif //LPC_SYSPLL_PDIV == xx
#if (LPC_SYSPLLIN_FREQUENCY * LPC_SYSPLL_MULT * LPC_SYSPLL_PDIV < 156000000UL) ||\
(LPC_SYSPLLIN_FREQUENCY * LPC_SYSPLL_MULT * LPC_SYSPLL_PDIV > 320000000UL)
#error "Please check the documentation about how to pick MULT and PDIV. \
current value gives a out of range CCO frequency"
#endif
#define LPC_MAINCLK_FREQUENCY (LPC_SYSPLLIN_FREQUENCY * LPC_SYSPLL_MULT)
#define LPC_SYSPLL_MSEL_VAL (LPC_SYSPLL_MULT - 1)
#else
#error "LPC_SYSPLL_MULT must be defined and btween 1 and 32, \
LPC_SYSPLL_PDIV must be one of 2, 4, 8, 16."
#endif
#else
#error "Invalid LPC_MAINCLKSEL. Must be one of SYSCON_MAINCLKSEL_IRC, \
SYSCON_MAINCLKSEL_PLLIN, SYSCON_MAINCLKSEL_WATCHDOG, SYSCON_MAINCLKSEL_PLLOUT"
#endif
#if !defined(LPC_SYS_DIV) || LPC_SYS_DIV < 1 || LPC_SYS_DIV > 255
#error "LPC_SYS_DIV must be between 1 and 255"
#else
#define LPC_SYS_FREQUENCY (LPC_MAINCLK_FREQUENCY / LPC_SYS_DIV)
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#include "nvic.h"
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void lpc_clock_init(void);
#ifdef __cplusplus
}
#endif
#endif /* HAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,56 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file LPC11Uxx/lpc_registry.h
* @brief LPC11U11 capabilities registry.
*
* @addtogroup HAL
* @{
*/
#ifndef LPC_REGISTRY_H_
#define LPC_REGISTRY_H_
/**
* @brief Sub-family identifier.
*/
#if defined(LPC11U35) || \
defined(__DOXYGEN__)
#define LPC11Uxx
#else
#error unknown/unsupported LPC11Uxx microcontroller
#endif
#if defined(LPC11Uxx) || defined(__DOXYGEN__)
/* USB attributes.*/
#define LPC_HAS_USB TRUE
#define LPC_USB_IRQ_VECTOR Vector98
#define LPC_SSP0_IRQ_VECTOR Vector90
#define LPC_SSP1_IRQ_VECTOR Vector78
#define LPC_UART_IRQ_VECTOR Vector94
#endif
/** @} */
#endif /* LPC_REGISTRY_H_ */
/** @} */

View File

@ -0,0 +1,17 @@
# List of all the LPC11Uxx platform files.
PLATFORMSRC := ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \
${CHIBIOS_CONTRIB}/os/hal/ports/LPC/LPC11Uxx/hal_lld.c
# Required include directories
PLATFORMINC = ${CHIBIOS}/os/hal/ports/common/ARMCMx \
${CHIBIOS_CONTRIB}/os/hal/ports/LPC/LPC11Uxx
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/STM/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/GPIO/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/SPI/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)
ALLINC += $(PLATFORMINC)