434 lines
14 KiB
C
434 lines
14 KiB
C
/*
|
|
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
|
LPC17xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
|
|
|
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 LPC17xx/hal_lld.h
|
|
* @brief HAL subsystem low level driver header template.
|
|
*
|
|
* @addtogroup HAL
|
|
* @{
|
|
*/
|
|
|
|
#ifndef _HAL_LLD_H_
|
|
#define _HAL_LLD_H_
|
|
|
|
#include "LPC17xx.h"
|
|
#include "nvic.h"
|
|
|
|
/*===========================================================================*/
|
|
/* Driver constants. */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* @brief Defines the support for realtime counters in the HAL.
|
|
*/
|
|
#define HAL_IMPLEMENTS_COUNTERS TRUE
|
|
|
|
/**
|
|
* @brief Platform name.
|
|
*/
|
|
#define PLATFORM_NAME "LPC17xx"
|
|
|
|
#define IRCOSCCLK 4000000UL /**< High speed internal clock. */
|
|
|
|
#define CLKSRCSEL_IRCOSC 0UL /**< Clock source is IRC. */
|
|
#define CLKSRCSEL_MAINOSC 1UL /**< Clock source is Main oscillator. */
|
|
#define CLKSRCSEL_RTCOSC 2UL /**< Clock source is RTC oscillator. */
|
|
|
|
#define PCLKSEL_CCLK_DIV_4 0UL /**< Peripheral clock source is CCLK/4 */
|
|
#define PCLKSEL_CCLK 1UL /**< Peripheral clock source is CCLK */
|
|
#define PCLKSEL_CCLK_DIV_2 2UL /**< Peripheral clock source is CCLK/2 */
|
|
#define PCLKSEL_CCLK_DIV_8 3UL /**< Peripheral clock source is CCLK/8 */
|
|
#define PCLKSEL_MASK 3UL
|
|
|
|
#define CLKOUTSEL_CCLK 0UL /**< Clock output is CPU clock. */
|
|
#define CLKOUTSEL_MAINOSC 1UL /**< Clock output is Main oscillator. */
|
|
#define CLKOUTSEL_IRCOSC 2UL /**< Clock output is IRC oscillator. */
|
|
#define CLKOUTSEL_USBCLK 3UL /**< Clock output is USB clock. */
|
|
#define CLKOUTSEL_RTCOSC 4UL /**< Clock output is RTC oscillator. */
|
|
|
|
#define PCLKSEL_CCLK_DIV_4 0UL /**< Peripheral clock output is CCLK/4 */
|
|
#define PCLKSEL_CCLK 1UL /**< Peripheral clock output is CCLK */
|
|
#define PCLKSEL_CCLK_DIV_2 2UL /**< Peripheral clock output is CCLK/2 */
|
|
#define PCLKSEL_CCLK_DIV_8 3UL /**< Peripheral clock output is CCLK/8 */
|
|
|
|
#define USBSEL_PLL0_DIV_6 5UL /**< USB clock source is PLL0/6. */
|
|
#define USBSEL_PLL0_DIV_7 7UL /**< USB clock source is PLL0/7. */
|
|
#define USBSEL_PLL0_DIV_9 9UL /**< USB clock source is PLL0/9. */
|
|
/*===========================================================================*/
|
|
/* Driver pre-compile time settings. */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* @brief Main oscillator enable.
|
|
*/
|
|
#if !defined(LPC17xx_MAINOSC_ENABLE) || defined(__DOXYGEN__)
|
|
#define LPC17xx_MAINOSC_ENABLE TRUE
|
|
#endif
|
|
|
|
/**
|
|
* @brief System PLL clock source select.
|
|
*/
|
|
#if !defined(LPC17xx_SYSCLK_SELECT) || defined(__DOXYGEN__)
|
|
#define LPC17xx_SYSCLK_SELECT CLKSRCSEL_MAINOSC
|
|
#endif
|
|
|
|
/**
|
|
* @brief Main PLL enable.
|
|
*/
|
|
#if !defined(LPC17xx_MAINPLL_ENABLE) || defined(__DOXYGEN__)
|
|
#define LPC17xx_MAINPLL_ENABLE TRUE
|
|
#endif
|
|
|
|
/**
|
|
* @brief Main PLL multiplier.
|
|
* @note Final frequency must not exceed the CCO ratings.
|
|
*/
|
|
#if !defined(LPC17xx_MAINPLL_MUL) || defined(__DOXYGEN__)
|
|
#define LPC17xx_MAINPLL_MUL 200
|
|
#endif
|
|
|
|
/**
|
|
* @brief Main PLL pre-divider.
|
|
* @note The value must be in the 1..32 range and the final frequency
|
|
* must not exceed the CCO ratings.
|
|
*/
|
|
#if !defined(LPC17xx_MAINPLL_PREDIV) || defined(__DOXYGEN__)
|
|
#define LPC17xx_MAINPLL_PREDIV 6
|
|
#endif
|
|
|
|
/**
|
|
* @brief USB PLL enable.
|
|
*/
|
|
#if !defined(LPC17xx_USBPLL_ENABLE) || defined(__DOXYGEN__)
|
|
#define LPC17xx_USBPLL_ENABLE FALSE
|
|
#endif
|
|
|
|
/**
|
|
* @brief USB PLL multiplier.
|
|
* @note The value must be in the 1..32 range and the final frequency
|
|
* must not exceed the CCO ratings and USB clock must be equal 48MHz.
|
|
*/
|
|
#if !defined(LPC17xx_USBPLL_MUL) || defined(__DOXYGEN__)
|
|
#define LPC17xx_USBPLL_MUL 4
|
|
#endif
|
|
|
|
/**
|
|
* @brief USB PLL divider.
|
|
* @note The value must be 2, 4, 8 or 16 and the final frequency
|
|
* must not exceed the CCO ratings and USB clock must be equal 48MHz.
|
|
*/
|
|
#if !defined(LPC17xx_USBPLL_DIV) || defined(__DOXYGEN__)
|
|
#define LPC17xx_USBPLL_DIV 4
|
|
#endif
|
|
|
|
/**
|
|
* @brief CPU clock divider.
|
|
* @note The value must be chosen between (1...255).
|
|
*/
|
|
#if !defined(LPC17xx_CCLK_DIV) || defined(__DOXYGEN__)
|
|
#define LPC17xx_CCLK_DIV 4
|
|
#endif
|
|
|
|
/**
|
|
* @brief PCLK clock select.
|
|
*/
|
|
#if !defined(LPC17xx_PCLK_SELECT) || defined(__DOXYGEN__)
|
|
#define LPC17xx_PCLK_SELECT PCLKSEL_CCLK
|
|
#endif
|
|
|
|
/**
|
|
* @brief Clock output enable.
|
|
* @note
|
|
*/
|
|
#if !defined(LPC17xx_CLKOUT_ENABLE) || defined(__DOXYGEN__)
|
|
#define LPC17xx_CLKOUT_ENABLE FALSE
|
|
#endif
|
|
|
|
/**
|
|
* @brief Clock output divider.
|
|
* @note The value must be chosen between (1...16).
|
|
*/
|
|
#if !defined(LPC17xx_CLKOUT_DIV) || defined(__DOXYGEN__)
|
|
#define LPC17xx_CLKOUT_DIV 4
|
|
#endif
|
|
|
|
/**
|
|
* @brief Clock output clock source select.
|
|
*/
|
|
#if !defined(LPC17xx_CLKOUT_SELECT) || defined(__DOXYGEN__)
|
|
#define LPC17xx_CLKOUT_SELECT CLKOUTSEL_MAINOSC
|
|
#endif
|
|
|
|
/**
|
|
* @brief USB clock PPL0 clock source select.
|
|
* @note PLL0 output must be 288MHz (USBSEL_PLL0_DIV_6), 384MHz (USBSEL_PLL0_DIV_8) or
|
|
* 480MHz(USBSEL_PLL0_DIV_10). Only is used when USB PLL (PLL1) disable.
|
|
*/
|
|
#if !defined(LPC17xx_USBCLKPLL0_SELECT) || defined(__DOXYGEN__)
|
|
#define LPC17xx_USBCLKPLL0_SELECT USBSEL_PLL0_DIV_6
|
|
#endif
|
|
/*===========================================================================*/
|
|
/* Derived constants and error checks. */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* @brief Calculated OSCRANGE setting.
|
|
*/
|
|
#if (MAINOSCCLK < 18000000) || defined(__DOXYGEN__)
|
|
#define LPC17xx_OSCRANGE 0
|
|
#else
|
|
#define LPC17xx_OSCRANGE 1
|
|
#endif
|
|
|
|
/**
|
|
* @brief PLL input clock frequency.
|
|
*/
|
|
#if (LPC17xx_SYSCLK_SELECT == CLKSRCSEL_IRCOSC) || defined(__DOXYGEN__)
|
|
#define LPC17xx_SYSCLK IRCOSCCLK
|
|
#elif LPC17xx_SYSCLK_SELECT == CLKSRCSEL_MAINOSC
|
|
#define LPC17xx_SYSCLK MAINOSCCLK
|
|
#elif LPC17xx_SYSCLK_SELECT == CLKSRCSEL_RTCOSC
|
|
#define LPC17xx_SYSCLK RTCOSCCLK
|
|
#else
|
|
#error "Invalid LPC17xx_SYSCLK_SELECT clock source specified."
|
|
#endif
|
|
|
|
/**
|
|
* @brief MSEL mask in SYSPLLCTRL register.
|
|
*/
|
|
#if ((LPC17xx_MAINPLL_MUL % 2) == 0) || defined(__DOXYGEN__)
|
|
#define LPC17xx_PLL0CFG_MSEL0 ((LPC17xx_MAINPLL_MUL/2) - 1)
|
|
#else
|
|
#error "Invalid LPC17xx_PLL0CFG_MUL value."
|
|
#endif
|
|
|
|
/**
|
|
* @brief PSEL mask in SYSPLLCTRL register.
|
|
*/
|
|
#if ((LPC17xx_MAINPLL_PREDIV >= 1) && (LPC17xx_MAINPLL_PREDIV <= 32)) || defined(__DOXYGEN__)
|
|
#define LPC17xx_PLL0CFG_NSEL0 (LPC17xx_MAINPLL_PREDIV - 1)
|
|
#else
|
|
#error "Invalid LPC17xx_MAINPLL_PREDIV value (1 to 32 accepted)."
|
|
#endif
|
|
|
|
/**
|
|
* @brief CCO frequency.
|
|
*/
|
|
#define LPC17xx_MAINPLLCCO ((LPC17xx_MAINPLL_MUL * \
|
|
LPC17xx_SYSCLK)/LPC17xx_MAINPLL_PREDIV)
|
|
|
|
#if (LPC17xx_MAINPLLCCO < 275000000) || (LPC17xx_SYSPLLCCO > 550000000)
|
|
#error "CCO frequency out of the acceptable range (275...550)."
|
|
#endif
|
|
|
|
/**
|
|
* @brief PLL output clock frequency.
|
|
*/
|
|
#if LPC17xx_MAINPLL_ENABLE
|
|
#define LPC17xx_MAINPLLCLK LPC17xx_MAINPLLCCO
|
|
#else
|
|
#define LPC17xx_MAINPLLCLK LPC17xx_SYSCLK
|
|
#endif
|
|
|
|
/**
|
|
* @brief CPU clock frequency.
|
|
* @note Most of LPC17xx have max 120 MHz clock.
|
|
*/
|
|
#define LPC17xx_CCLK (LPC17xx_MAINPLLCLK/LPC17xx_CCLK_DIV)
|
|
#if (LPC17xx_CCLK > 120000000) || defined(__DOXYGEN__)
|
|
#error "CPU Clock out of range."
|
|
#endif
|
|
|
|
#if LPC17xx_USBPLL_ENABLE
|
|
/**
|
|
* @brief Main oscillator out of range.
|
|
*/
|
|
#if ((MAINOSCCLK < 10000000) && (MAINOSCCLK > 25000000)) || defined(__DOXYGEN__)
|
|
#error "Main oscillator clock out of range."
|
|
#endif
|
|
|
|
/**
|
|
* @brief MSEL1 mask in PLL1CFG register.
|
|
*/
|
|
#if (LPC17xx_USBPLL_MUL >= 1) && (LPC17xx_USBPLL_MUL <= 32) || defined(__DOXYGEN__)
|
|
#define LPC17xx_PLL1CFG_MSEL1 (LPC17xx_USBPLL_MUL - 1)
|
|
#else
|
|
#error "Invalid LPC17xx_USBPLL_MUL value (1 to 32 accepted)."
|
|
#endif
|
|
|
|
/**
|
|
* @brief PSEL1 mask in PLL1CFG register.
|
|
*/
|
|
#if (LPC17xx_USBPLL_DIV == 2) || defined(__DOXYGEN__)
|
|
#define LPC17xx_PLL1CFG_PSEL1 0UL
|
|
#elif (LPC17xx_USBPLL_DIV == 4)
|
|
#define LPC17xx_PLL1CFG_PSEL1 1UL
|
|
#elif (LPC17xx_USBPLL_DIV == 8)
|
|
#define LPC17xx_PLL1CFG_PSEL1 2UL
|
|
#elif (LPC17xx_USBPLL_DIV == 16)
|
|
#define LPC17xx_PLL1CFG_PSEL1 3UL
|
|
#else
|
|
#error "Invalid LPC17xx_USBPLL_DIV value (2, 4, 8, 16 accepted)."
|
|
#endif
|
|
|
|
/**
|
|
* @brief USB PLL CCO frequency.
|
|
*/
|
|
#define LPC17xx_USBPLLCCO (MAINOSCCLK * LPC17xx_USBPLL_MUL * \
|
|
LPC17xx_USBPLL_DIV)
|
|
|
|
#if (LPC17xx_USBPLLCCO < 156000000) || (LPC17xx_SYSPLLCCO > 320000000)
|
|
#error "CCO frequency out of the acceptable range (156...320)"
|
|
#endif
|
|
|
|
/**
|
|
* @brief USB clock frequency.
|
|
* @note Must be 48 MHz.
|
|
*/
|
|
#define LPC17xx_USBCLK (LPC17xx_USBPLLCCO/LPC17xx_USBPLL_DIV)
|
|
#if (LPC17xx_USBCLK != 48000000) || defined(__DOXYGEN__)
|
|
#error "USB clock out of range."
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* @brief Peripheral clock frequency.
|
|
*/
|
|
#if (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_4) || defined(__DOXYGEN__)
|
|
#define LPC17xx_PCLK (LPC17xx_CCLK/4)
|
|
#define LPC17xx_PCLKSEL0 0x00
|
|
#define LPC17xx_PCLKSEL1 0x00
|
|
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK)
|
|
#define LPC17xx_PCLK (LPC17xx_CCLK)
|
|
#define LPC17xx_PCLKSEL0 0x55515155
|
|
#define LPC17xx_PCLKSEL1 0x54555455
|
|
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_2)
|
|
#define LPC17xx_PCLK (LPC17xx_CCLK/2)
|
|
#define LPC17xx_PCLKSEL0 0xAAA2A2AA
|
|
#define LPC17xx_PCLKSEL1 0xA8AAA8AA
|
|
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_8)
|
|
#define LPC17xx_PCLK (LPC17xx_CCLK/8)
|
|
#define LPC17xx_PCLKSEL0 0xFFF3F3FF
|
|
#define LPC17xx_PCLKSEL1 0xFCFFFCFF
|
|
#else
|
|
#error "Invalid LPC17xx_PCLK_SELECT value"
|
|
#endif
|
|
|
|
/**
|
|
* @brief LPC17xx_CLKOUT_DIV out of range.
|
|
*/
|
|
#if ((LPC17xx_CLKOUT_DIV < 1) && (LPC17xx_CLKOUT_DIV > 16)) || defined(__DOXYGEN__)
|
|
#error "Invalid LPC17xx_CLKOUT_DIV value (1 to 16 accepted)."
|
|
#endif
|
|
|
|
/**
|
|
* @brief CLKOUT frequency.
|
|
*/
|
|
#if (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_CCLK) || defined(__DOXYGEN__)
|
|
#define LPC17xx_CLKOUTCLK (LPC17xx_CCLK/LPC17xx_CLKOUT_DIV)
|
|
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_MAINOSC)
|
|
#define LPC17xx_CLKOUTCLK (MAINOSCCLK/LPC17xx_CLKOUT_DIV)
|
|
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_IRCOSC)
|
|
#define LPC17xx_CLKOUTCLK (IRCOSCCLK/LPC17xx_CLKOUT_DIV)
|
|
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_USBCLK)
|
|
#define LPC17xx_CLKOUTCLK (LPC17xx_USBCLK/LPC17xx_CLKOUT_DIV)
|
|
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_RTCOSC)
|
|
#define LPC17xx_CLKOUTCLK (RTCOSCCLK/LPC17xx_CLKOUT_DIV)
|
|
#else
|
|
#error "Invalid LPC17xx_CLKOUT_SELECT value."
|
|
#endif
|
|
|
|
/**
|
|
* @brief CLKOUT frequency out of range.
|
|
*/
|
|
#if (LPC17xx_CLKOUTCLK > 50000000) || defined(__DOXYGEN__)
|
|
#error "CLKOUT frequency out of the acceptable range (less than 50 MHz)"
|
|
#endif
|
|
|
|
/**
|
|
* @brief Flash wait states.
|
|
*/
|
|
#if (LPC17xx_CCLK <= 20000000) || defined(__DOXYGEN__)
|
|
#define LPC17xx_FLASHCFG_FLASHTIM 0UL
|
|
#elif LPC17xx_CCLK <= 40000000
|
|
#define LPC17xx_FLASHCFG_FLASHTIM 1UL
|
|
#elif LPC17xx_CCLK <= 60000000
|
|
#define LPC17xx_FLASHCFG_FLASHTIM 2UL
|
|
#elif LPC17xx_CCLK <= 80000000
|
|
#define LPC17xx_FLASHCFG_FLASHTIM 3UL
|
|
#elif LPC17xx_CCLK <= 120000000
|
|
#define LPC17xx_FLASHCFG_FLASHTIM 4UL
|
|
#else
|
|
#define LPC17xx_FLASHCFG_FLASHTIM 5UL
|
|
#endif
|
|
|
|
/*===========================================================================*/
|
|
/* Driver data structures and types. */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* @brief Type of the realtime free counter value.
|
|
*/
|
|
typedef uint32_t halrtcnt_t;
|
|
|
|
/*===========================================================================*/
|
|
/* Driver macros. */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* @brief Returns the current value of the system free running counter.
|
|
* @note This service is implemented by returning the content of the
|
|
* DWT_CYCCNT register.
|
|
*
|
|
* @return The value of the system free running counter of
|
|
* type halrtcnt_t.
|
|
*
|
|
* @notapi
|
|
*/
|
|
#define hal_lld_get_counter_value() DWT_CYCCNT
|
|
|
|
/**
|
|
* @brief Realtime counter frequency.
|
|
* @note The DWT_CYCCNT register is incremented directly by the cpu
|
|
* clock so this function returns LPC17xx_CCLK.
|
|
*
|
|
* @return The realtime counter frequency of type halclock_t.
|
|
*
|
|
* @notapi
|
|
*/
|
|
#define hal_lld_get_counter_frequency() LPC17xx_CCLK
|
|
|
|
/*===========================================================================*/
|
|
/* External declarations. */
|
|
/*===========================================================================*/
|
|
|
|
#include "lpc17xx_dma.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
void hal_lld_init(void);
|
|
void LPC17xx_clock_init(void);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _HAL_LLD_H_ */
|
|
|
|
/** @} */
|