Merge pull request #226 from fishman/nuc123sd4an0

Nuvoton NUC123SD4AN0 MCU port
This commit is contained in:
Fabien Poussin 2020-11-21 18:26:33 +01:00 committed by GitHub
commit efdb0ce711
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 12071 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
/**************************************************************************//**
* @file system_NUC123SD4AN0.h
* @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File for
* Device NUC123SD4AN0
* @version V5.00
* @date 13. May 2019
******************************************************************************/
/*
* Copyright (c) 2019 /u/KeepItUnder. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* 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.
*/
#ifndef SYSTEM_NUC123SD4AN0_H /* ToDo: replace '<Device>' with your device name */
#define SYSTEM_NUC123SD4AN0_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**
* Frequency Defines
*
* See NUC123 Technical Reference Manual 5.4.2, page 103
*
*/
#define __HXT (12000000ul) // PCB-mounted High Frequency Crystal (12MHz)
#define __HIRC (22118400ul) // Internal MCU-block HF Oscillator Frequency (22.1184MHz)
#define __LXT (32768ul) // PCB-mounted Low Frequency Crystal (32kHz)
#define __LIRC (10000ul) // Internal MCU-block LF Oscillator Frequency (10kHz)
#define __HSI (50000000ul) // PLL clock (50MHz)
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
extern uint32_t CyclesPerUs; /*!< Cycles per micro second */
extern uint32_t PllClock; /*!< PLL Output Clock Frequency */
/**
\brief Setup the microcontroller system.
Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/**
\brief Update SystemCoreClock variable.
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
extern void SystemUnlockReg (void);
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_NUC123SD4AN0_H */

View File

@ -0,0 +1,85 @@
/*
ChibiOS - Copyright (C) 2006..2016 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.
*/
/*
* NUC123SD4AN0 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 = 0x20000000, len = 20k
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);
/* Generic rules inclusion.*/
INCLUDE rules.ld

View File

@ -0,0 +1,19 @@
# List of the ChibiOS generic NUC123SD4AN0 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)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
STARTUPINC = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/devices/NUC123SD4AN0 \
$(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld \
$(CHIBIOS)/os/common/ext/CMSIS/include \
$(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
$(CHIBIOS_CONTRIB)/os/common/ext/CMSIS/Nuvoton/NUMICRO
STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld
# Shared variables
ALLXASMSRC += $(STARTUPASM)
ALLCSRC += $(STARTUPSRC)
ALLINC += $(STARTUPINC)

View File

@ -0,0 +1,85 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 NUC123SD4AN0/cmparams.h
* @brief ARM Cortex-M0 parameters for the NUC123SD4AN0.
*
* @defgroup ARMCMx_NUC123 NUC123SD4AN0 Specific Parameters
* @ingroup ARMCMx_SPECIFIC
* @details This file contains the Cortex-M0 specific parameters for the
* NUC123SD4AN0 platform.
* @{
*/
#ifndef CMPARAMS_H
#define CMPARAMS_H
/**
* @brief Cortex core model.
*/
#define CORTEX_MODEL 0
/**
* @brief Floating Point unit presence.
*/
#define CORTEX_HAS_FPU 0
/**
* @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
/* The following code is not processed when the file is included from an
asm module.*/
#if !defined(_FROM_ASM_)
/* If the device type is not externally defined, for example from the Makefile,
then a file named board.h is included. This file must contain a device
definition compatible with the vendor include file.*/
#if !defined (NUC123SD4AN0)
#include "board.h"
#endif
/* 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 "NUC123.h"
#include "NUC123SD4AN0.h"
/*lint -save -e9029 [10.4] Signedness comes from external files, it is
unpredictable but gives no problems.*/
#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
/*lint -restore*/
#endif /* !defined(_FROM_ASM_) */
#endif /* CMPARAMS_H */
/** @} */

View File

@ -0,0 +1,2 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/CLKv1/hal_clks_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/CLKv1

View File

@ -0,0 +1,511 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 CLKv1/hal_clks_lld.c
* @brief CLK subsystem low level driver code.
*
* @addtogroup CLKS
* @{
*/
#include "hal.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* WDT_ModuleNum
* ADC_ModuleNum
* SPI0_ModuleNum
* SPI1_ModuleNum
* SPI2_ModuleNum
* TMR0_ModuleNum
* TMR1_ModuleNum
* TMR2_ModuleNum
* TMR3_ModuleNum
* UART0_ModuleNum
* UART1_ModuleNum
* PWM01_ModuleNum
* PWM23_ModuleNum
* I2S_ModuleNum
* FDIV_ModuleNum
* WWDT_ModuleNum
* USBD_ModuleNum
* I2C0_ModuleNum
* I2C1_ModuleNum
* PS2_ModuleNum
* PDMA_ModuleNum
* ISP_ModuleNum
*
*/
bool clks_module_hxt_source[22] = { 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
bool clks_module_hirc_source[22] = { 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
bool clks_module_lirc_source[22] = { 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
bool clks_module_hclk_source[22] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
bool clks_module_pll_source[22] = { 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
bool clks_module_ext_source[22] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
bool clks_module_divider[22] = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 };
uint32_t clks_module_enable[22] = { CLK_APBCLK_WDT_EN_Msk,
CLK_APBCLK_ADC_EN_Msk,
CLK_APBCLK_SPI0_EN_Msk,
CLK_APBCLK_SPI1_EN_Msk,
CLK_APBCLK_SPI2_EN_Msk,
CLK_APBCLK_TMR0_EN_Msk,
CLK_APBCLK_TMR1_EN_Msk,
CLK_APBCLK_TMR2_EN_Msk,
CLK_APBCLK_TMR3_EN_Msk,
CLK_APBCLK_UART0_EN_Msk,
CLK_APBCLK_UART1_EN_Msk,
CLK_APBCLK_PWM01_EN_Msk,
CLK_APBCLK_PWM23_EN_Msk,
CLK_APBCLK_I2S_EN_Msk,
CLK_APBCLK_FDIV_EN_Msk,
0,
CLK_APBCLK_USBD_EN_Msk,
CLK_APBCLK_I2C0_EN_Msk,
CLK_APBCLK_I2C1_EN_Msk,
CLK_APBCLK_PS2_EN_Msk,
CLK_AHBCLK_PDMA_EN_Msk,
CLK_AHBCLK_ISP_EN_Msk };
uint32_t clks_module_sel1_mask[22] = { CLK_CLKSEL1_WDT_S_Msk,
CLK_CLKSEL1_ADC_S_Msk,
CLK_CLKSEL1_SPI0_S_Msk,
CLK_CLKSEL1_SPI1_S_Msk,
CLK_CLKSEL1_SPI2_S_Msk,
CLK_CLKSEL1_TMR0_S_Msk,
CLK_CLKSEL1_TMR1_S_Msk,
CLK_CLKSEL1_TMR2_S_Msk,
CLK_CLKSEL1_TMR3_S_Msk,
CLK_CLKSEL1_UART_S_Msk,
CLK_CLKSEL1_UART_S_Msk,
CLK_CLKSEL1_PWM01_S_Msk,
CLK_CLKSEL1_PWM23_S_Msk,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level CLK driver initialization.
*
* @notapi
*/
/** @brief Set Core Clock
*
* @description Set the core system clock some reference speed (Hz).
* This should be between 25MHz and 72MHz for the NUC123SD4AN0.
*
* Use either the HXT (exact) or HIRC (nearest using 22.1184MHz)
* as the clock source.
*
*/
uint32_t clks_lld_set_core_clock(uint32_t clkCore)
{
uint32_t stableHIRC;
/* Read HIRC clock source stable flag */
stableHIRC = CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk;
/* Setup __HIRC */
CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Use __HIRC as HCLK temporarily */
CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_Msk;
CLK->CLKDIV &= (~CLK_CLKDIV_HCLK_N_Msk);
/* Is HXT stable ? */
if(CLK->CLKSTATUS & CLK_CLKSTATUS_XTL12M_STB_Msk) {
/* Use __HXT as PLL source */
clkCore = clks_lld_enable_pll(CLK_PLLCON_PLL_SRC_HXT, (clkCore << 1));
} else {
/* Use __HIRC as PLL source */
clkCore = clks_lld_enable_pll(CLK_PLLCON_PLL_SRC_HIRC, (clkCore << 1));
/* Read HIRC clock source stable flag again (since we're using it now) */
stableHIRC = CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk;
}
/* Set HCLK clock source to PLL */
clks_lld_set_HCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_CLKDIV_HCLK(2));
/* Disable HIRC if HIRC was disabled before we started */
if (stableHIRC == 0) {
CLK->PWRCON &= ~CLK_PWRCON_OSC22M_EN_Msk;
}
/* Return actual HCLK frequency is PLL frequency divide 2 */
return (clkCore >> 1);
}
/** @brief Set system HCLK
*
* @description Setup HCLK source and divider
*
* Always switch to a known stable clock source before changing a
* system clock, to avoid issues related to the original clock's
* speed/settings.
*
*/
void clks_lld_set_HCLK(uint32_t clkSource, uint32_t clkDivider)
{
uint32_t stableHIRC;
/* Read HIRC clock source stable flag */
stableHIRC = CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk;
/* Setup __HIRC */
CLK->PWRCON |= CLK_CLKSTATUS_OSC22M_STB_Msk;
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Use __HIRC as HCLK, temporarily */
CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLK_S_Msk)) | CLK_CLKSEL0_HCLK_S_HIRC;
/* Set new clock divider */
CLK->CLKDIV = (CLK->CLKDIV & (~CLK_CLKDIV_HCLK_N_Msk)) | clkDivider;
/* Switch HCLK to new HCLK source */
CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLK_S_Msk)) | clkSource;
/* Update System Core Clock */
SystemCoreClockUpdate();
/* Disable HIRC if HIRC was disabled before we started */
if (stableHIRC == 0) {
CLK->PWRCON &= ~CLK_CLKSTATUS_OSC22M_STB_Msk;
}
}
void clks_lld_set_module_clock(uint32_t module, uint32_t clkSource, uint32_t clkDivider)
{
/* Set clock source */
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~(clks_module_sel1_mask[module]))) | clkSource;
/* Set secondary clock source bit for PWM01/PWM23 */
if (module == PWM01_ModuleNum) {
CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_PWM01_S_Msk)) | (clkSource & CLK_CLKSEL2_PWM01_S_Msk);
} else if (module == PWM23_ModuleNum) {
CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_PWM23_S_Msk)) | (clkSource & CLK_CLKSEL2_PWM23_S_Msk);
}
/* Set clock divider */
if (clks_module_divider[module]) {
switch (module) {
case ADC_ModuleNum:
CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_ADC_N_Msk) | clkDivider;
break;
case UART0_ModuleNum:
case UART1_ModuleNum:
CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_UART_N_Msk) | clkDivider;
break;
case USBD_ModuleNum:
CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_USB_N_Msk) | clkDivider;
break;
default:
break;
}
}
}
void clks_lld_enable_ck0(uint32_t clkSource, uint32_t clkDivider)
{
CLK->FRQDIV = (CLK_FRQDIV_DIVIDER_EN_Msk | clkDivider) ;
clks_lld_enable_module_clock(FDIV_ModuleNum);
clks_lld_set_module_clock(FDIV_ModuleNum, clkSource, 0);
}
/**
* @brief Enable module clock
*
* @description Module clock enables are all in either AHBCLK or APBCLK
* Register masks are stored in a table to save knowing bit width
*
*/
void clks_lld_enable_module_clock(uint32_t clkModule) {
switch (clkModule) {
case PDMA_ModuleNum:
case ISP_ModuleNum:
/* AHB Clocks */
CLK->AHBCLK |= clks_module_enable[clkModule];
break;
case WWDT_ModuleNum:
/* No Module Clock */
break;
default:
/* APB Clocks */
CLK->APBCLK |= clks_module_enable[clkModule];
break;
}
}
/**
* @brief Disable module clock
*
* @description Module clock enables are all in either AHBCLK or APBCLK
* Register masks are stored in a table to save knowing bit width
*
*/
void clks_lld_disable_module_clock(uint32_t clkModule) {
switch (clkModule) {
case PDMA_ModuleNum:
case ISP_ModuleNum:
/* AHB Clocks */
CLK->AHBCLK &= ~clks_module_enable[clkModule];
break;
case WWDT_ModuleNum:
/* No Module Clock */
break;
default:
/* APB Clocks */
CLK->APBCLK &= ~clks_module_enable[clkModule];
break;
}
}
uint32_t clks_lld_enable_pll(uint32_t pllSrc, uint32_t pllFreq)
{
/* Disable PLL first to avoid unstable when setting PLL. */
CLK->PLLCON = CLK_PLLCON_PD_Msk;
/* Check and setup correct clock source */
switch (pllSrc) {
case CLK_PLLCON_PLL_SRC_HXT:
/* Use HXT clock */
CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;
/* Wait for stable HXT */
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_XTL12M_STB_Msk);
break;
case CLK_PLLCON_PLL_SRC_HIRC:
/* Use HIRC clock */
CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;
/* Wait for stable HIRC */
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_OSC22M_STB_Msk);
break;
}
/**
* Calculate best PLL variables from requested frequency
*
* See NUC123 Technical Reference Manual 5.4.8 PLL Control Register Description, page 124
*
* NF 1
* FOUT = FIN x -- x --
* NR NO
*
*/
uint32_t NO = 0;
uint32_t NR = 0;
uint32_t clkCalc = 0;
/* Set "NO" for requested frequency */
/* We're using "NO" first to set the PLLCON - so make it "NO" - 1; */
if (pllFreq >= FREQ_25MHZ && pllFreq <= FREQ_50MHZ) {
/* Low frequency - use full variable headroom */
pllFreq <<= 2;
NO = 3;
} else if (pllFreq > FREQ_50MHZ && pllFreq <= FREQ_100MHZ) {
/* Medium frequency - use full variable headroom */
pllFreq <<= 1;
NO = 1;
} else if (pllFreq > FREQ_100MHZ && pllFreq <= FREQ_200MHZ) {
/* High frequency - full variable headroom already used */
NO = 0;
} else {
/* Frequency out of range - use default PLL settings
*
* See NUC123 Technical Reference Manual PLL COntrol Register Description, page 124
* The default value: 0xC22E
* FIN = 12 MHz
* NR = (1+2) = 3
* NF = (46+2) = 48
* NO = 4
* FOUT = 12/4 x 48 x 1/3 = 48 MHz
*/
if (pllSrc == CLK_PLLCON_PLL_SRC_HXT) {
CLK->PLLCON = 0xC22E;
} else {
CLK->PLLCON = 0xD66F;
}
/* Wait for stable PLL clock */
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_PLL_STB_Msk);
return clks_lld_get_pll_clock_freq();
}
/* Setup "NR" and clkCalc */
switch (pllSrc) {
case CLK_PLLCON_PLL_SRC_HXT:
NR = 2;
clkCalc = __HXT;
break;
case CLK_PLLCON_PLL_SRC_HIRC:
NR = 4;
clkCalc = __HIRC;
break;
}
/**
* Loop to calculate best/lowest NR (between 0 or 2 and 31) and best/lowest NF (between 0 and 511)
*
* Best results are off-by-2 until final equation calculation (to allow use in PLLCON)
*
*/
uint32_t bestNR = 0;
uint32_t bestNF = 0;
uint32_t minLimit = -1;
while (NR <= 33) {
uint32_t tmpCalc1 = clkCalc / NR;
if (tmpCalc1 > 1600000 && tmpCalc1 < 16000000) {
uint32_t NF = 2;
while (NF <= 513) {
uint32_t tmpCalc2 = tmpCalc1 * NF;
if (tmpCalc2 >= 100000000 && tmpCalc2 <= 200000000) {
uint32_t tmpCalc3;
if (tmpCalc2 > pllFreq) {
tmpCalc3 = tmpCalc2 - pllFreq;
} else {
tmpCalc3 = pllFreq - tmpCalc2;
}
if (tmpCalc3 < minLimit) {
minLimit = tmpCalc3;
bestNF = NF;
bestNR = NR;
/* Stop NF calc loop when minLimit tends back to 0 */
if(minLimit == 0)
break;
}
}
NF++;
}
}
NR++;
}
/* Enable and apply new PLL setting. */
CLK->PLLCON = pllSrc | (NO << 14) | ((bestNR - 2) << 9) | (bestNF - 2);
/* Wait for stable PLL clock */
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_PLL_STB_Msk);
/* Return equation result */
return (clkCalc / ((NO + 1) * bestNR) * bestNF);
}
/**
* @brief Wait for stable clock
*
* @description Always wait around 300ms for clock to be stable
*
*/
uint32_t clks_lld_wait_for_clock_ready(uint32_t clkMask)
{
int32_t timeout = 2180000;
while (timeout-- > 0) {
if ((CLK->CLKSTATUS & clkMask) == clkMask) {
return 1;
}
}
return 0;
}
void clks_lld_enable_SysTick(uint32_t clkSrc, uint32_t count) {
// Disable the counter
clks_lld_disable_SysTick();
// Clear current values/flags
SysTick->VAL = 0;
// Set SysTick Clock Source
switch (clkSrc) {
case CLK_CLKSEL0_STCLK_S_HCLK:
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
break;
default:
CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLK_S_Msk) | clkSrc;
// CLK->CLKSEL0 |= SysTick_CTRL_CLKSOURCE_Msk;
break;
}
// Set reload value
SysTick->LOAD = count;
// Enable Interrupt and Counter
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}
void clks_lld_disable_SysTick(void) {
/* Disable System Tick counter */
SysTick->CTRL = 0;
}
/** @} */

View File

@ -0,0 +1,222 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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_clks_lld.h
* @brief Clock/Timer subsystem low level header.
*
* @addtogroup CLKS
* @{
*/
#ifndef HAL_CLKS_LLD_H
#define HAL_CLKS_LLD_H
// #if HAL_USE_CLKS || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define FREQ_25MHZ 25000000
#define FREQ_50MHZ 50000000
#define FREQ_72MHZ 72000000
#define FREQ_100MHZ 100000000
#define FREQ_200MHZ 200000000
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL0 */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL0_HCLK_S_HXT (0x0ul<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Set HCLK clock source as HXT */
#define CLK_CLKSEL0_HCLK_S_PLL_DIV2 (0x1ul<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Set HCLK clock source as PLL/2 */
#define CLK_CLKSEL0_HCLK_S_PLL (0x2ul<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Set HCLK clock source as PLL */
#define CLK_CLKSEL0_HCLK_S_LIRC (0x3ul<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Set HCLK clock source as LIRC */
#define CLK_CLKSEL0_HCLK_S_HIRC (0x7ul<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Set HCLK clock source as HIRC */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL1 */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL1_TMR0_S_HXT (0x0ul<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Set TMR0 clock source as HXT */
#define CLK_CLKSEL1_TMR0_S_HCLK (0x2ul<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Set TMR0 clock source as HCLK */
#define CLK_CLKSEL1_TMR0_S_EXT_TRG (0x3ul<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Set TMR0 clock source as external trigger */
#define CLK_CLKSEL1_TMR0_S_LIRC (0x5ul<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Set TMR0 clock source as LIRC */
#define CLK_CLKSEL1_TMR0_S_HIRC (0x7ul<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Set TMR0 clock source as HIRC */
#define CLK_CLKSEL1_TMR1_S_HXT (0x0ul<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Set TMR1 clock source as HXT */
#define CLK_CLKSEL1_TMR1_S_HCLK (0x2ul<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Set TMR1 clock source as HCLK */
#define CLK_CLKSEL1_TMR1_S_EXT_TRG (0x3ul<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Set TMR1 clock source as external trigger */
#define CLK_CLKSEL1_TMR1_S_LIRC (0x5ul<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Set TMR1 clock source as LIRC */
#define CLK_CLKSEL1_TMR1_S_HIRC (0x7ul<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Set TMR1 clock source as HIRC*/
#define CLK_CLKSEL1_TMR2_S_HXT (0x0ul<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Set TMR2 clock source as external X'tal */
#define CLK_CLKSEL1_TMR2_S_HCLK (0x2ul<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Set TMR2 clock source as HCLK */
#define CLK_CLKSEL1_TMR2_S_EXT_TRG (0x3ul<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Set TMR2 clock source as external trigger */
#define CLK_CLKSEL1_TMR2_S_LIRC (0x5ul<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Set TMR2 clock source as LIRC */
#define CLK_CLKSEL1_TMR2_S_HIRC (0x7ul<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Set TMR2 clock source as HIRC */
#define CLK_CLKSEL1_TMR3_S_HXT (0x0ul<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Set TMR3 clock source as HXT */
#define CLK_CLKSEL1_TMR3_S_HCLK (0x2ul<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Set TMR3 clock source as HCLK */
#define CLK_CLKSEL1_TMR3_S_EXT_TRG (0x3ul<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Set TMR3 clock source as external trigger */
#define CLK_CLKSEL1_TMR3_S_LIRC (0x5ul<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Set TMR3 clock source as LIRC */
#define CLK_CLKSEL1_TMR3_S_HIRC (0x7ul<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Set TMR3 clock source as HIRC */
#define CLK_CLKSEL1_PWM01_S_HXT (0x0ul<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Set PWM01 clock source as HXT */
#define CLK_CLKSEL1_PWM01_S_HCLK (0x2ul<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Set PWM01 clock source as HCLK */
#define CLK_CLKSEL1_PWM01_S_HIRC (0x3ul<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Set PWM01 clock source as HIRC */
#define CLK_CLKSEL1_PWM01_S_LIRC (0x3ul<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Set PWM01 clock source as LIRC */
#define CLK_CLKSEL1_PWM23_S_HXT (0x0ul<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Set PWM23 clock source as HXT */
#define CLK_CLKSEL1_PWM23_S_HCLK (0x2ul<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Set PWM23 clock source as HCLK */
#define CLK_CLKSEL1_PWM23_S_HIRC (0x3ul<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Set PWM23 clock source as HIRC */
#define CLK_CLKSEL1_PWM23_S_LIRC (0x3ul<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Set PWM23 clock source as LIRC */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL2 */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL2_PWM01_EXT_HXT (0x0ul<<CLK_CLKSEL2_PWM01_S_Pos) /*!< Set PWM01 clock source as HXT */
#define CLK_CLKSEL2_PWM01_EXT_HCLK (0x0ul<<CLK_CLKSEL2_PWM01_S_Pos) /*!< Set PWM01 clock source as HCLK */
#define CLK_CLKSEL2_PWM01_EXT_HIRC (0x0ul<<CLK_CLKSEL2_PWM01_S_Pos) /*!< Set PWM01 clock source as HIRC */
#define CLK_CLKSEL2_PWM01_EXT_LIRC (0x1ul<<CLK_CLKSEL2_PWM01_S_Pos) /*!< Set PWM01 clock source as LIRC */
#define CLK_CLKSEL2_PWM23_EXT_HXT (0x0ul<<CLK_CLKSEL2_PWM23_S_Pos) /*!< Set PWM23 clock source as HXT */
#define CLK_CLKSEL2_PWM23_EXT_HCLK (0x0ul<<CLK_CLKSEL2_PWM23_S_Pos) /*!< Set PWM23 clock source as HCLK */
#define CLK_CLKSEL2_PWM23_EXT_HIRC (0x0ul<<CLK_CLKSEL2_PWM23_S_Pos) /*!< Set PWM23 clock source as HIRC */
#define CLK_CLKSEL2_PWM23_EXT_LIRC (0x1ul<<CLK_CLKSEL2_PWM23_S_Pos) /*!< Set PWM23 clock source as LIRC */
#define CLK_CLKSEL2_FRQDIV_S_HXT (0x0ul<<CLK_CLKSEL2_FRQDIV_S_Pos) /*!< Set FRQDIV clock source as HXT */
#define CLK_CLKSEL2_FRQDIV_S_HCLK (0x2ul<<CLK_CLKSEL2_FRQDIV_S_Pos) /*!< Set FRQDIV clock source as HCLK */
#define CLK_CLKSEL2_FRQDIV_S_HIRC (0x3ul<<CLK_CLKSEL2_FRQDIV_S_Pos) /*!< Set FRQDIV clock source as HIRC */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKDIV */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKDIV_HCLK(x) ((x)-1) /*!< HCLK clock divider (1~16) */
#define CLK_CLKDIV_USB(x) (((x)-1) << CLK_CLKDIV_USB_N_Pos) /*!< USB clock divider (1~16) */
/*---------------------------------------------------------------------------------------------------------*/
/* PLLCON */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_PLLCON_PLL_SRC_HXT 0x00000000ul /*!< Set PLL clock source as HXT */
#define CLK_PLLCON_PLL_SRC_HIRC 0x00080000ul /*!< Set PLL clock source as HIRC */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
// extern DACDriver DACD1;
#ifdef __cplusplus
extern "C" {
#endif
// void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv);
// void CLK_EnableModuleClock(uint32_t u32ModuleIdx);
// void CLK_DisableModuleClock(uint32_t u32ModuleIdx);
// uint32_t CLK_WaitClockReady(uint32_t u32ClkMask);
// void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count);
// void CLK_DisableSysTick(void);
/**
* @brief Get PLL clock frequency
* @param None
* @return PLL frequency
* @details This function get PLL frequency. The frequency unit is Hz.
*/
static inline uint32_t clks_lld_get_pll_clock_freq(void) {
uint32_t PllReg;
uint32_t pllFIN, pllNF, pllNR, pllNO;
PllReg = CLK->PLLCON;
if(PllReg & (CLK_PLLCON_PD_Msk | CLK_PLLCON_OE_Msk)) {
PllClock = 0; /* PLL is in power down mode or fix low */
} else {
if (PllReg & CLK_PLLCON_PLL_SRC_HIRC) {
pllFIN = __HIRC; /* Use HXT for PLL clock */
} else {
pllFIN = __HXT; /* Use HXT for PLL clock */
}
if (PllReg & CLK_PLLCON_BP_Msk) {
PllClock = pllFIN;
} else {
switch (((PllReg & CLK_PLLCON_OUT_DV_Msk) >> CLK_PLLCON_OUT_DV_Pos)) {
case 0b00: // OUT_DIV == 00 : NO = 1
pllNO = 1;
break;
case 0b11: // OUT_DIV == 11 : NO = 4
pllNO = 4;
break;
default: // OUT_DIV == 01 or 10 : NO = 2
pllNO = 2;
break;
}
pllNF = ((PllReg & CLK_PLLCON_FB_DV_Msk) >> CLK_PLLCON_FB_DV_Pos) + 2;
pllNR = ((PllReg & CLK_PLLCON_IN_DV_Msk) >> CLK_PLLCON_IN_DV_Pos) + 2;
/* shift to avoid overflow condition */
PllClock = (((pllFIN >> 2) * pllNF) / (pllNR * pllNO) << 2);
}
}
return PllClock;
}
uint32_t clks_lld_set_core_clock(uint32_t clkCore);
void clks_lld_set_HCLK(uint32_t clkSource, uint32_t clkDivider);
void clks_lld_set_module_clock(uint32_t module, uint32_t clkSource, uint32_t clkDivider);
void clks_lld_enable_ck0(uint32_t clkSource, uint32_t clkDivider);
void clks_lld_enable_module_clock(uint32_t moduleIdx);
void clks_lld_disable_module_clock(uint32_t moduleIdx);
uint32_t clks_lld_enable_pll(uint32_t pllSrc, uint32_t pllFreq);
uint32_t clks_lld_wait_for_clock_ready(uint32_t clkMask);
void clks_lld_enable_SysTick(uint32_t clkSource, uint32_t count);
void clks_lld_disable_SysTick(void);
#ifdef __cplusplus
}
#endif
#endif /* HAL_CLK_LLD_H */
/** @} */

View File

@ -0,0 +1,10 @@
# PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/GPIOv1/gpio.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/GPIOv1
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/GPIOv1/hal_pal_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/GPIOv1/hal_pal_lld.c
endif

View File

@ -0,0 +1,196 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 PLATFORM 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. */
/*===========================================================================*/
/* DEBUG
OSAL_IRQ_HANDLER(NUC123_GPIOAB_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
OSAL_IRQ_HANDLER(NUC123_GPIOCDF_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief NUC123 I/O ports configuration.
* @details Ports A-D(E, F, G, H) clocks enabled.
*
* @param[in] config the NUC123 ports configuration
*
* @notapi
*/
void _pal_lld_init(const PALConfig *config) {
//(void)config;
/* Turn on GPIO subsystem
* Set all GPIO to Input/HZ
* Clear all GPIO Interrupts
* Set all GPIO Interrupt Modes to Level
* Turn off DeBounce
* Zero all GPIO Outputs (just in case)
*/
GPIOA->PMD = config->PAData.PMD;
GPIOA->OFFD = config->PAData.OFFD;
GPIOA->DMASK = config->PAData.DMASK;
GPIOA->DBEN = config->PAData.DBEN;
GPIOA->IMD = config->PAData.IMD;
GPIOA->IEN = config->PAData.IEN;
GPIOA->ISRC = config->PAData.ISRC;
GPIOA->DOUT = config->PAData.DOUT;
GPIOB->PMD = config->PBData.PMD;
GPIOB->OFFD = config->PBData.OFFD;
GPIOB->DMASK = config->PBData.DMASK;
GPIOB->DBEN = config->PBData.DBEN;
GPIOB->IMD = config->PBData.IMD;
GPIOB->IEN = config->PBData.IEN;
GPIOB->ISRC = config->PBData.ISRC;
GPIOB->DOUT = config->PBData.DOUT;
GPIOC->PMD = config->PCData.PMD;
GPIOC->OFFD = config->PCData.OFFD;
GPIOC->DMASK = config->PCData.DMASK;
GPIOC->DBEN = config->PCData.DBEN;
GPIOC->IMD = config->PCData.IMD;
GPIOC->IEN = config->PCData.IEN;
GPIOC->ISRC = config->PCData.ISRC;
GPIOC->DOUT = config->PCData.DOUT;
GPIOD->PMD = config->PDData.PMD;
GPIOD->OFFD = config->PDData.OFFD;
GPIOD->DMASK = config->PDData.DMASK;
GPIOD->DBEN = config->PDData.DBEN;
GPIOD->IMD = config->PDData.IMD;
GPIOD->IEN = config->PDData.IEN;
GPIOD->ISRC = config->PDData.ISRC;
GPIOD->DOUT = config->PDData.DOUT;
GPIOF->PMD = config->PFData.PMD;
GPIOF->OFFD = config->PFData.OFFD;
GPIOF->DMASK = config->PFData.DMASK;
GPIOF->DBEN = config->PFData.DBEN;
GPIOF->IMD = config->PFData.IMD;
GPIOF->IEN = config->PFData.IEN;
GPIOF->ISRC = config->PFData.ISRC;
GPIOF->DOUT = config->PFData.DOUT;
/* Set DeBounce conditions */
GPIO_DBNCE->DBNCECON = 0x04u;
/* Enable External Crystal Oscillator pins */
SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;
// SYS->GPD_MFP |= SYS_GPD_MFP_PD10_CLKO;
/* Enable UART1 data pins */
SYS->GPB_MFP |= SYS_GPB_MFP_PB1_UART0_TXD | SYS_GPB_MFP_PB0_UART0_RXD;
}
/**
* @brief 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) {
uint32_t nucMode = 0;
if (mode == PAL_MODE_INPUT || mode == PAL_MODE_INPUT_PULLUP)
nucMode = GPIO_PMD_INPUT;
else if (mode == PAL_MODE_OUTPUT_OPENDRAIN)
nucMode = GPIO_PMD_OPEN_DRAIN;
else if (mode == PAL_MODE_OUTPUT_PUSHPULL)
nucMode = GPIO_PMD_OUTPUT;
else
nucMode = GPIO_PMD_QUASI;
// GPIO_SetMode(port, mask, nucMode);
for (uint32_t i = 0; i < PAL_IOPORTS_WIDTH; i++) {
// for(uint32_t i = 0; i < GPIO_PINSPERPORT_MAX; i++) {
if(mask & (1 << i)) {
port->PMD = (port->PMD & ~(0x03ul << (i << 1))) | (nucMode << (i << 1));
}
}
}
#endif /* HAL_USE_PAL == TRUE */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1/hal_st_lld.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1/hal_pwm_lld.c
#PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1/timer.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1

View File

@ -0,0 +1,231 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 TIMv1/hal_pwm_lld.c
* @brief PWM subsystem low level driver header.
*
* @addtogroup PWM
* @{
*/
#include "hal.h"
// #if HAL_USE_PWM || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level PWM driver initialization.
*
* @notapi
*/
// void pwm_lld_init(void) {
// }
void pwm_lld_start(PWM_T *pwm, uint32_t mask) {
uint32_t pwmStart = 0;
for(uint32_t i = 0; i < PWM_CHANNELS; i++) {
if (mask & (1 << i)) {
pwmStart |= (PWM_PCR_CH0EN_Msk << (i * 8));
}
}
(pwm)->PCR |= pwmStart;
}
void pwm_lld_enable_period_int(PWM_T *pwm, uint32_t pwmChannel, uint32_t periodType) {
(pwm)->PIER = ((pwm)->PIER & ~(0x01ul << (pwmChannel >> 1))) | (0x01ul << pwmChannel) | (periodType << (pwmChannel >> 1));
}
void pwm_lld_disable_period_int(PWM_T *pwm, uint32_t pwmChannel) {
(pwm)->PIER &= ~(PWM_PIER_PWMIE0_Msk << pwmChannel);
}
uint32_t pwm_lld_get_period_int(PWM_T *pwm, uint32_t pwmChannel) {
if ((pwm)->PIIR & (0x01ul << (pwmChannel))) {
return 1;
} else {
return 0;
}
}
void pwm_lld_clear_period_int(PWM_T *pwm, uint32_t pwmChannel) {
(pwm)->PIIR = (0x01ul << pwmChannel);
}
uint32_t pwm_lld_config_output_channel(PWM_T *pwm, uint32_t channel, uint32_t freq, uint32_t duty)
{
uint32_t regSource;
uint32_t clkSource;
uint32_t pwmClk;
uint8_t divider = 1;
uint8_t prescale = 0xFF;
uint16_t CNR = 0xFFFF;
if (channel < 2) {
regSource = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM01_S_Msk)) >> (CLK_CLKSEL2_PWM01_S_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk)) >> (CLK_CLKSEL1_PWM01_S_Pos);
} else {
regSource = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM23_S_Msk)) >> (CLK_CLKSEL2_PWM23_S_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM23_S_Msk)) >> (CLK_CLKSEL1_PWM23_S_Pos);
}
if (regSource == 2) {
SystemCoreClockUpdate();
clkSource = SystemCoreClock;
} else {
switch (regSource) {
case 0:
clkSource = __HXT;
break;
case 1:
case 4:
case 5:
case 6:
clkSource = 0;
break;
case 2:
SystemCoreClockUpdate();
clkSource = SystemCoreClock;
break;
case 3:
clkSource = __HIRC;
break;
case 7:
clkSource = __LIRC;
break;
}
}
/* Calculate best divider */
while (divider < 17) {
pwmClk = (clkSource / (freq)) / divider;
// If pwmClk is larger than (CNR * prescale) then divider can still be bigger
if (pwmClk > (0x10000 * 0x100)) {
continue;
}
// Set prescaler to CNR value lower than 0xFFFF
prescale = (pwmClk + 0xFFFF) / 0x10000;
// Keep prescale bigger than 2 this loop
if (prescale < 3) {
prescale = 2;
}
pwmClk /= prescale;
if (pwmClk <= 0x10000) {
if (pwmClk == 1) {
CNR = 1; // Too fast, and PWM cannot generate expected frequency...
} else {
CNR = pwmClk;
}
break;
}
divider = divider << 1;
}
pwmClk = clkSource / (prescale * divider * CNR);
/* Calculate PWM Registers */
prescale -= 1;
CNR -= 1;
/* Set final divider for output calculation */
switch (divider) {
case 1:
divider = 4;
break;
case 4:
divider = 1;
break;
case 8:
divider = 2;
break;
case 16:
divider = 3;
break;
case 0:
case 2:
case 3:
case 5:
case 6:
case 7:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
default:
divider = 0;
break;
}
// Prescaler is shared every two channels (01/23/etc.)
(pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_CP01_Msk << ((channel >> 1) * 8))) | (prescale << ((channel >> 1) * 8));
(pwm)->CSR = ((pwm)->CSR & ~(PWM_CSR_CSR0_Msk << (4 * channel))) | (divider << (4 * channel));
// Set edge-aligned PWM
(pwm)->PCR &= ~(PWM_PCR_PWM01TYPE_Msk << (channel >> 1));
(pwm)->PCR |= PWM_PCR_CH0MOD_Msk << (8 * channel);
// Set PWM register values
if (duty) {
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CMR0)) + channel * 12))) = duty * (CNR + 1) / 100 - 1;
} else {
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CMR0)) + channel * 12))) = 0;
}
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CNR0)) + channel * 12))) = CNR;
return(pwmClk);
}
// #endif /* HAL_USE_PWM */
/** @} */

View File

@ -0,0 +1,120 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 TIMv1/hal_pwm_lld.h
* @brief PWM subsystem low level driver header.
*
* @addtogroup PWM
* @{
*/
#ifndef HAL_PWM_LLD_H
#define HAL_PWM_LLD_H
// #if HAL_USE_PWM || defined(__DOXYGEN__)
// #include "stm32_tim.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Number of PWM channels per PWM driver.
*/
#define PWM_CHANNELS (4)
#define PWM_CH0 0x0ul
#define PWM_CH1 0x1ul
#define PWM_CH2 0x2ul
#define PWM_CH3 0x3ul
#define PWM_EDGE_ALIGNED (0x0ul) /*!< Edge aligned */
#define PWM_CENTER_ALIGNED (0x01ul) /*!< Center aligned */
#define PWM_CLK_DIV_1 (0x04ul) /*!< Divide by 1 */
#define PWM_CLK_DIV_2 (0x0ul) /*!< Divide by 2 */
#define PWM_CLK_DIV_4 (0x01ul) /*!< Divide by 4 */
#define PWM_CLK_DIV_8 (0x02ul) /*!< Divide by 8 */
#define PWM_CLK_DIV_16 (0x03ul) /*!< Divide by 16 */
#define PWM_PERIOD_INT_UNDERFLOW (0) /*!< Period interrupt - counter underflow */
#define PWM_PERIOD_INT_MATCH_CNR (PWM_PIER_INT01TYPE_Msk) /*!< Period interrupt - counter matches CNR */
#define PWM_CAPTURE_INT_RISING_LATCH (PWM_CCR0_CRL_IE0_Msk) /*!< Capture interrupt - rising latch */
#define PWM_CAPTURE_INT_FALLING_LATCH (PWM_CCR0_CFL_IE0_Msk) /*!< Capture interrupt - falling latch */
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Configuration checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
// void pwm_lld_init(void);
// void pwm_lld_start(PWMDriver *pwmp);
// void pwm_lld_stop(PWMDriver *pwmp);
// void pwm_lld_enable_channel(PWMDriver *pwmp,
// pwmchannel_t channel,
// pwmcnt_t width);
// void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
// void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
// void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
// void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
// pwmchannel_t channel);
// void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
// pwmchannel_t channel);
// void pwm_lld_serve_interrupt(PWMDriver *pwmp);
void pwm_lld_enable_period_int(PWM_T *pwm, uint32_t pwmChannel, uint32_t periodType);
void pwm_lld_disable_period_int(PWM_T *pwm, uint32_t pwmChannel);
void pwm_lld_start(PWM_T *pwm, uint32_t mask);
void pwm_lld_clear_period_int(PWM_T *pwm, uint32_t pwmChannel);
uint32_t pwm_lld_get_period_int(PWM_T *pwm, uint32_t pwmChannel);
uint32_t pwm_lld_config_output_channel(PWM_T *pwm, uint32_t channel, uint32_t freq, uint32_t duty);
#ifdef __cplusplus
}
#endif
// #endif /* HAL_USE_PWM */
#endif /* HAL_PWM_LLD_H */
/** @} */

View File

@ -0,0 +1,376 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 TIMv1/hal_st_lld.c
* @brief ST Driver subsystem low level driver code.
*
* @addtogroup ST
* @{
*/
#include "hal.h"
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
#if (OSAL_ST_RESOLUTION == 32)
#define ST_ARR_INIT 0xFFFFFFFF
#else
#define ST_ARR_INIT 0x0000FFFF
#endif
#if NUC123_ST_USE_TIMER == 2
#if (OSAL_ST_RESOLUTION == 32) && !NUC123_TIM2_IS_32BITS
#error "TIM2 is not a 32bits timer"
#endif
#if defined(NUC123_TIM2_IS_USED)
#error "ST requires TIM2 but the timer is already used"
#else
#define NUC123_TIM2_IS_USED
#endif
#define ST_HANDLER NUC123_TIM2_HANDLER
#define ST_NUMBER NUC123_TIM2_NUMBER
#define ST_USE_TIMER TIMER2
#elif NUC123_ST_USE_TIMER == 3
#if (OSAL_ST_RESOLUTION == 32) && !NUC123_TIM3_IS_32BITS
#error "TIM3 is not a 32bits timer"
#endif
#if defined(NUC123_TIM3_IS_USED)
#error "ST requires TIM3 but the timer is already used"
#else
#define NUC123_TIM3_IS_USED
#endif
#define ST_HANDLER NUC123_TIM3_HANDLER
#define ST_NUMBER NUC123_TIM3_NUMBER
#define ST_USE_TIMER TIMER3
#elif NUC123_ST_USE_TIMER == 4
#if (OSAL_ST_RESOLUTION == 32) && !NUC123_TIM4_IS_32BITS
#error "TIM4 is not a 32bits timer"
#endif
#if defined(NUC123_TIM4_IS_USED)
#error "ST requires TIM4 but the timer is already used"
#else
#define NUC123_TIM4_IS_USED
#endif
#define ST_HANDLER NUC123_TIM4_HANDLER
#define ST_NUMBER NUC123_TIM4_NUMBER
#define ST_USE_TIMER TIMER4
#else
#error "NUC123_ST_USE_TIMER specifies an unsupported timer"
#endif
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
/*===========================================================================*/
/* 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 */
#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
/**
* @brief TIM2 interrupt handler.
* @details This interrupt is used for system tick in free running mode.
*
* @isr
*/
OSAL_IRQ_HANDLER(ST_HANDLER) {
OSAL_IRQ_PROLOGUE();
/* Note, under rare circumstances an interrupt can remain latched even if
the timer SR register has been cleared, in those cases the interrupt
is simply ignored.*/
if (NUC123_ST_TIM->TISR & TIMER_TISR_TIF_Msk) {
// TIMER_ClearIntFlag(NUC123_ST_TIM);
NUC123_ST_TIM->TISR = TIMER_TISR_TIF_Msk;
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
}
OSAL_IRQ_EPILOGUE();
}
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
/* DEBUG - Catch unused Interrupt Vectors and output to test pins
OSAL_IRQ_HANDLER(Vector7C){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB8);
GPIO_TOGGLE(PB11);
OSAL_IRQ_EPILOGUE();
}
OSAL_IRQ_HANDLER(NUC123_TIM3_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
OSAL_IRQ_HANDLER(NUC123_TIM4_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
OSAL_IRQ_HANDLER(NUC123_ADC_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
OSAL_IRQ_HANDLER(NUC123_USB1_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
OSAL_IRQ_HANDLER(NUC123_PDMA_HANDLER){
OSAL_IRQ_PROLOGUE();
GPIO_TOGGLE(PB4);
GPIO_TOGGLE(PB5);
GPIO_TOGGLE(PB6);
GPIO_TOGGLE(PB7);
GPIO_TOGGLE(PB8);
OSAL_IRQ_EPILOGUE();
}
//OSAL_IRQ_HANDLER(HardFault_Handler){
// OSAL_IRQ_PROLOGUE();
// NVIC_SystemReset();
// OSAL_IRQ_EPILOGUE();
//}
*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ST driver initialization.
*
* @notapi
*/
void st_lld_init(void) {
#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
/* Free running counter mode.*/
/* Enabling timer clock.*/
st_lld_timer_open(ST_USE_TIMER, TIMER_MODE_CONTINUOUS, OSAL_ST_FREQUENCY);
/* Initializing the counter in free running mode.*/
/* NUC123_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1;
NUC123_ST_TIM->ARR = ST_ARR_INIT;
NUC123_ST_TIM->CCMR1 = 0;
NUC123_ST_TIM->CCR[0] = 0;
NUC123_ST_TIM->DIER = 0;
NUC123_ST_TIM->CR2 = 0;
NUC123_ST_TIM->EGR = TIM_EGR_UG;
NUC123_ST_TIM->CR1 = TIM_CR1_CEN;
*/
/* IRQ enabled.*/
nvicEnableVector(ST_NUMBER, NUC123_ST_IRQ_PRIORITY);
// TIMER_EnableInt(ST_USE_TIMER);
ST_USE_TIMER->TCSR |= TIMER_TCSR_IE_Msk;
/* Start the Timer! */
// TIMER_Start(ST_USE_TIMER);
ST_USE_TIMER->TCSR |= TIMER_TCSR_CEN_Msk;
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
/* Periodic systick mode, the Cortex-Mx internal systick timer is used
in this mode.*/
// CLK_EnableSysTick(CLK_CLKSEL0_STCLK_S_HCLK, (NUC123_HCLK / OSAL_ST_FREQUENCY) - 1);
SysTick->LOAD = (NUC123_HCLK / OSAL_ST_FREQUENCY) - 1;
SysTick->VAL = 0;
SysTick->CTRL = (~SysTick_CTRL_CLKSOURCE_Msk) &
(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
/* IRQ enabled.*/
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, NUC123_ST_IRQ_PRIORITY);
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
}
#else /* OSAL_ST_MODE == OSAL_ST_MODE_NONE!!! */
#error "We can't proceed without an OSAL_ST clock!"
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
uint32_t st_lld_timer_getmoduleclock(TIMER_T *timer) {
uint32_t clkSource;
if (timer == TIMER0) {
clkSource = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0_S_Msk) >> CLK_CLKSEL1_TMR0_S_Pos;
} else if (timer == TIMER1) {
clkSource = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1_S_Msk) >> CLK_CLKSEL1_TMR1_S_Pos;
} else if (timer == TIMER2) {
clkSource = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2_S_Msk) >> CLK_CLKSEL1_TMR2_S_Pos;
} else {
clkSource = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3_S_Msk) >> CLK_CLKSEL1_TMR3_S_Pos;
}
if (clkSource == 2) {
return(SystemCoreClock);
}
switch (clkSource) {
case 0: // Clock source is HXT
return __HXT;
break;
case 5: // Clock source is LIRC
return __LIRC;
break;
case 7: // Clock source is HIRC
return __HIRC;
break;
default: // All other clock sources return 0
return 0;
}
}
uint32_t st_lld_timer_open(TIMER_T *timer, uint32_t tmrMode, uint32_t tmrFreq) {
uint32_t tmrClk = st_lld_timer_getmoduleclock(timer);
uint32_t cmpr = 0;
uint32_t prescale = 0;
// Fastest possible timer working freq is (tmrClk / 2). While cmpr = 2, pre-scale = 0.
if (tmrFreq > (tmrClk / 2)) {
cmpr = 2;
} else {
if (tmrClk >= 0x4000000) {
prescale = 7; // prescaler value - 1
tmrClk >>= 3;
} else if (tmrClk >= 0x2000000) {
prescale = 3; // prescaler value - 1
tmrClk >>= 2; // Divide Clock by 4 in preparation
} else if (tmrClk >= 0x1000000) {
prescale = 1; // prescaler value - 1
tmrClk >>= 1; // Divide Clock by 2 in preparation
}
cmpr = tmrClk / tmrFreq;
}
timer->TCSR = tmrMode | prescale;
timer->TCMPR = cmpr;
return (tmrClk / (cmpr * (prescale + 1)));
}
void st_lld_timer_close(TIMER_T *timer) {
timer->TCSR = 0;
timer->TEXCON = 0;
}
/** @} */

View File

@ -0,0 +1,225 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 ST Driver 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 "mcuconf.h"
/*
* Registry definitions.
*/
#include "nuc123_registry.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define CLK_CLKSEL0_STCLK_S_HXT (0x0ul<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Set HXT as STCLK clock source */
#define CLK_CLKSEL0_STCLK_S_HXT_DIV2 (0x2ul<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Set HXT/2 as STCLK clock source */
#define CLK_CLKSEL0_STCLK_S_HCLK_DIV2 (0x3ul<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Set HCLK/2 as STCLK clock source */
#define CLK_CLKSEL0_STCLK_S_HIRC_DIV2 (0x7ul<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Set HIRC/2 as STCLK clock source */
#define CLK_CLKSEL0_STCLK_S_HCLK (0x1ul<<SysTick_CTRL_CLKSOURCE_Pos) /*!< Set HCLK as STCLK clock source */
#define TIMER_MODE_PERIODIC (0x01ul << TIMER_TCSR_MODE_Pos)
#define TIMER_MODE_CONTINUOUS (0x03ul << TIMER_TCSR_MODE_Pos)
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief SysTick timer IRQ priority.
*/
#if !defined(NUC123_ST_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NUC123_ST_IRQ_PRIORITY 8
#endif
/**
* @brief TIMx unit (by number) to be used for free running operations.
* @note You must select a 32 bits timer if a 32 bits @p systick_t type
* is required.
* @note Timers 2, 3 and 4 are supported.
*/
#if !defined(NUC123_ST_USE_TIMER) || defined(__DOXYGEN__)
#define NUC123_ST_USE_TIMER 2
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if NUC123_ST_USE_TIMER == 2
#if !NUC123_HAS_TIM2
#error "TIM2 not present"
#endif
#define NUC123_ST_TIM TIMER1
#elif NUC123_ST_USE_TIMER == 3
#if !NUC123_HAS_TIM3
#error "TIM3 not present"
#endif
#define NUC123_ST_TIM TIMER2
#elif NUC123_ST_USE_TIMER == 4
#if !NUC123_HAS_TIM4
#error "TIM4 not present"
#endif
#define NUC123_ST_TIM TIMER3
#else
#error "NUC123_ST_USE_TIMER specifies an unsupported timer"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void st_lld_init(void);
uint32_t st_lld_timer_getmoduleclock(TIMER_T *timer);
uint32_t st_lld_timer_open(TIMER_T *timer, uint32_t tmrMode, uint32_t tmrFreq);
void st_lld_timer_close(TIMER_T *timer);
#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)NUC123_ST_TIM->TDR;
}
/**
* @brief Sets the alarm time.
*
* @param[in] time the time to be set for the next alarm
*
* @notapi
*/
static inline void st_lld_set_alarm(systime_t time) {
// TIMER_SET_CMP_VALUE(NUC123_ST_TIM, (uint32_t)time);
NUC123_ST_TIM->TCMPR = (uint32_t)time;
}
/**
* @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)NUC123_ST_TIM->TCMPR;
}
/**
* @brief Starts the alarm.
* @note Makes sure that no spurious alarms are triggered after
* this call.
*
* @param[in] time the time to be set for the first alarm
*
* @notapi
*/
static inline void st_lld_start_alarm(systime_t time) {
// NUC123_ST_TIM->TCMP = (uint32_t)time;
// NUC123_ST_TIM->SR = 0;
// NUC123_ST_TIM->DIER = NUC123_TIM_DIER_CC1IE;
st_lld_timer_open(NUC123_ST_TIM, TIMER_MODE_CONTINUOUS | TIMER_TCSR_TDR_EN_Msk, st_lld_timer_getmoduleclock(NUC123_ST_TIM));
//TIMER_SET_CMP_VALUE(NUC123_ST_TIM, (uint32_t)time);
// NUC123_ST_TIM->TCMPR = (uint32_t)time;
st_lld_set_alarm(time);
// TIMER_SET_PRESCALE_VALUE(NUC123_ST_TIM, 0);
NUC123_ST_TIM->TCSR = (NUC123_ST_TIM->TCSR & ~TIMER_TCSR_PRESCALE_Msk) | 0;
// TIMER_Start(NUC123_ST_TIM);
NUC123_ST_TIM->TCSR |= TIMER_TCSR_CEN_Msk;
}
/**
* @brief Stops the alarm interrupt.
*
* @notapi
*/
static inline void st_lld_stop_alarm(void) {
// TIMER_DisableInt(NUC123_ST_TIM);
NUC123_ST_TIM->TCSR &= ~TIMER_TCSR_IE_Msk;
}
/**
* @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 (bool)(((NUC123_ST_TIM->TISR & TIMER_TISR_TIF_Msk) & (NUC123_ST_TIM->TCSR & TIMER_TCSR_CACT_Msk)) != 0);
}
#endif /* HAL_ST_LLD_H */
/** @} */

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/USBv1/hal_usb_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/USBv1/hal_usb_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/USBv1

View File

@ -0,0 +1,570 @@
/*
ChibiOS - Copyright (C) 2017 Frank Zschockelt
ChibiOS - Copyright (C) 2019 /u/KeepItUnder
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 NUC123 USB subsystem low level driver source.
*
* @addtogroup USB
* @{
*/
#include "hal.h"
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief USB1 driver identifier.
*/
#if (NUC123_USB_USE_USB1 == TRUE) || defined(__DOXYGEN__)
USBDriver USBD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
uint8_t * const usbd_sram = (uint8_t*)(USBD_BASE + 0x100);
/**
* @brief EP0 state.
*/
/**
* @brief IN EP0 state.
*/
USBInEndpointState ep0_in;
/**
* @brief OUT EP0 state.
*/
USBOutEndpointState ep0_out;
static uint8_t ep0setup_buffer[8];
/**
* @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
USB_EP_MODE_TYPE_CTRL,
_usb_ep0setup,
_usb_ep0in,
_usb_ep0out,
0x40,
0x40,
&ep0_in,
&ep0_out,
1,
ep0setup_buffer
};
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
void _toggle_dsq(int ep, uint8_t *dsq)
{
if (*dsq) {
USBD->EP[ep].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
}
else {
USBD->EP[ep].CFG |= USBD_CFG_DSQ_SYNC_Msk;
}
*dsq = !*dsq;
}
/*===========================================================================*/
/* Driver interrupt handlers and threads. */
/*===========================================================================*/
static void serve_endpoint_irq(USBDriver *usbp,
uint32_t endpoint_mask,
uint32_t epstatus)
{
for (int hwEp = 0; hwEp < USB_MAX_ENDPOINTS; hwEp++) {
if (endpoint_mask & (1 << hwEp)) {
uint32_t bus_status = ((epstatus >> (hwEp*(USBD_EPSTS_EPSTS1_Pos - USBD_EPSTS_EPSTS0_Pos))) & USBD_EPSTS_EPSTS0_Msk) >> USBD_EPSTS_EPSTS0_Pos;
usbep_t ep = (USBD->EP[hwEp].CFG & USBD_CFG_EP_NUM_Msk) >> USBD_CFG_EP_NUM_Pos;
switch (bus_status) {
case 0: /* In ACK */
{
USBInEndpointState *iesp = usbp->epc[ep]->in_state;
iesp->txcnt += USBD->EP[hwEp].MXPLD;
if (iesp->txcnt >= iesp->txsize) {
_usb_isr_invoke_in_cb(usbp, ep);
}
else {
uint32_t txcnt;
if ((iesp->txcnt + usbp->epc[ep]->in_maxsize) > iesp->txsize) {
txcnt = iesp->txsize - iesp->txcnt;
}
else {
txcnt = usbp->epc[ep]->in_maxsize;
}
for (uint32_t n = 0; n < txcnt; n++) {
usbd_sram[(USBD->EP[hwEp].BUFSEG) + n] = iesp->txbuf[iesp->txcnt + n];
}
_toggle_dsq(hwEp, &(iesp->dsq));
USBD->EP[hwEp].MXPLD = txcnt;
}
}
break;
case 0x1: /* In NAK */
break;
case 0x2: /* Out Packet Data 0 ACK */
case 0x6: /* Out Packet Data 1 ACK */
{
USBOutEndpointState *oesp = usbp->epc[ep]->out_state;
for (uint32_t n = 0; n < USBD->EP[hwEp].MXPLD; n++) {
oesp->rxbuf[oesp->rxcnt] = usbd_sram[USBD->EP[hwEp].BUFSEG + n];
oesp->rxcnt++;
}
if (oesp->rxcnt == oesp->rxsize) {
_usb_isr_invoke_out_cb(usbp, ep);
}
else {
_toggle_dsq(hwEp, &(oesp->dsq));
if ((oesp->rxcnt + usbp->epc[ep]->out_maxsize) > oesp->rxsize) {
USBD->EP[hwEp].MXPLD = oesp->rxsize - oesp->rxcnt;
}
else {
USBD->EP[hwEp].MXPLD = usbp->epc[ep]->out_maxsize;
}
}
}
break;
case 0x3: /* Setup ACK */
break;
case 0x7: /* Isochronous transfer end */
default:
osalDbgAssert(FALSE, "not supported");
}
}
}
}
static void serve_usb_irq(USBDriver *usbp) {
uint32_t intsts = USBD->INTSTS;
uint32_t epsts = USBD->EPSTS;
if (intsts & USBD_INTSTS_FLDET_STS_Msk) {
USBD->INTSTS |= USBD_INTSTS_FLDET_STS_Msk;
if (USBD->FLDET) {
usbConnectBus(usbp);
}
else {
usbDisconnectBus(usbp);
}
}
if (intsts & USBD_INTSTS_BUS_STS_Msk) {
uint32_t bus_attr = USBD->ATTR;
USBD->INTSTS |= USBD_INTSTS_BUS_STS_Msk;
if (bus_attr & USBD_ATTR_USBRST_Msk) {
_usb_reset(usbp);
}
if (bus_attr & USBD_ATTR_SUSPEND_Msk) {
if (usbp->state == USB_ACTIVE) {
_usb_suspend(usbp);
}
}
if (bus_attr & USBD_ATTR_RESUME_Msk) {
usbConnectBus(usbp);
(usbp)->receiving = 0;
(usbp)->transmitting = 0;
_usb_wakeup(usbp);
}
}
if (intsts & USBD_INTSTS_USB_STS_Msk) {
/* check endpoints first */
serve_endpoint_irq(usbp, (intsts & USBD_INTSTS_EPEVT_Msk) >> USBD_INTSTS_EPEVT_Pos, epsts);
USBD->INTSTS = intsts & USBD_INTSTS_EPEVT_Msk;
/* then handle setup packets */
if (intsts & USBD_INTSTS_SETUP_Msk) {
USBD->INTSTS |= USBD_INTSTS_SETUP_Msk;
USBInEndpointState *iesp = usbp->epc[0]->in_state;
iesp->dsq = 0;
_usb_isr_invoke_setup_cb(usbp, 0);
}
}
if (intsts & USBD_INTSTS_WAKEUP_STS_Msk) {
USBD->INTSTS |= USBD_INTSTS_WAKEUP_STS_Msk;
USBD->ATTR |= USBD_ATTR_PHY_EN_Msk;
}
}
OSAL_IRQ_HANDLER(NUC123_USB1_HANDLER) {
OSAL_IRQ_PROLOGUE();
serve_usb_irq(&USBD1);
OSAL_IRQ_EPILOGUE();
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level USB driver initialization.
*
* @notapi
*/
void usb_lld_init(void) {
#if NUC123_USB_USE_USB1 == TRUE
/* Driver initialization.*/
usbObjectInit(&USBD1);
#endif
}
/**
* @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 NUC123_USB_USE_USB1 == TRUE
if (&USBD1 == usbp) {
uint16_t delay;
/* Enable USB Clock */
UNLOCKREG();
CLK->APBCLK |= CLK_APBCLK_USBD_EN_Msk;
/* Reset USB */
SYS->IPRSTC2 |= SYS_IPRSTC2_USBD_RST_Msk;
for (delay=0x100; delay > 0; delay--);
SYS->IPRSTC2 &= ~SYS_IPRSTC2_USBD_RST_Msk;
LOCKREG();
usbConnectBus(usbp);
USBD->ATTR = (USBD_ATTR_BYTEM_Msk | USBD_ATTR_PWRDN_Msk |
USBD_ATTR_DPPU_EN_Msk |USBD_ATTR_USB_EN_Msk |
USBD_ATTR_PHY_EN_Msk);
USBD->DRVSE0 = 1u;
for (delay=0x100; delay > 0; delay--);
USBD->DRVSE0 = 0u;
USBD->INTSTS = USBD->INTSTS;
nvicEnableVector(NUC123_USB1_NUMBER, NUC123_USB_USB1_IRQ_PRIORITY);
USBD->INTEN = (USBD_INTEN_WAKEUP_EN_Msk |
USBD_INTEN_WAKEUP_IE_Msk |
USBD_INTEN_FLDET_IE_Msk |
USBD_INTEN_USB_IE_Msk |
USBD_INTEN_BUS_IE_Msk);
}
#endif
}
}
/**
* @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 NUC123_USB_USE_USB1 == TRUE
if (&USBD1 == usbp) {
}
#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.*/
/* EP0 initialization.*/
usbp->epc[0] = &ep0config;
/* NUC123 has 512b SRAM for EP-buffers; the first 8b are reserved for setup packets */
usbp->bufnext = 8;
usbp->epnext = 0;
usb_lld_init_endpoint(usbp, 0);
usbConnectBus(usbp);
USBD->FADDR = 0;
}
/**
* @brief Sets the USB address.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_set_address(USBDriver *usbp) {
USBD->FADDR = usbp->address;
}
uint32_t usb_alloc_buf(USBDriver *usbp, size_t size) {
uint32_t buf;
buf = usbp->bufnext;
usbp->bufnext += size;
osalDbgAssert(usbp->bufnext <= 512, "usb buffer space full");
return buf;
}
/**
* @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) {
const USBEndpointConfig *epcp = usbp->epc[ep];
uint8_t hwep;
if (epcp->in_state != NULL) {
hwep = usbp->epnext;
usbp->epnext += 1;
osalDbgAssert(usbp->epnext <= USB_MAX_ENDPOINTS, "No endpoints left");
USBD->EP[hwep].BUFSEG = usb_alloc_buf(usbp, epcp->in_maxsize);
if (epcp->ep_mode == USB_EP_MODE_TYPE_CTRL)
/* 2 == in */
USBD->EP[hwep].CFG = (ep << USBD_CFG_EP_NUM_Pos) | (2 << USBD_CFG_STATE_Pos) | USBD_CFG_CSTALL_Msk;
else
USBD->EP[hwep].CFG = (ep << USBD_CFG_EP_NUM_Pos) | (2 << USBD_CFG_STATE_Pos);
epcp->in_state->hwEp = hwep;
}
if (epcp->out_state != NULL) {
hwep = usbp->epnext;
usbp->epnext += 1;
osalDbgAssert(usbp->epnext <= USB_MAX_ENDPOINTS, "No endpoints left");
USBD->EP[hwep].BUFSEG = usb_alloc_buf(usbp, epcp->out_maxsize);
if (epcp->ep_mode == USB_EP_MODE_TYPE_CTRL)
/* 1 == Out */
USBD->EP[hwep].CFG = (ep << USBD_CFG_EP_NUM_Pos) | (1 << USBD_CFG_STATE_Pos) | USBD_CFG_CSTALL_Msk;
else
USBD->EP[hwep].CFG = (ep << USBD_CFG_EP_NUM_Pos) | (1 << USBD_CFG_STATE_Pos);
epcp->out_state->hwEp = hwep;
}
}
/**
* @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) {
(void)usbp;
for (int i = 0; i < USB_MAX_ENDPOINTS; i++) {
USBD->EP[i].CFGP |= USBD_CFGP_CLRRDY_Msk;
USBD->EP[i].CFG &= ~USBD_CFG_STATE_Msk;
}
}
/**
* @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) {
(void)usbp;
(void)ep;
return EP_STATUS_DISABLED;
}
/**
* @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) {
return EP_STATUS_DISABLED;
}
/**
* @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) {
(void)usbp;
(void)ep;
int i;
for (i = 0; i < 8; i++) {
*buf = usbd_sram[i];
//*buf = ep0setup_buffer[i];
ep0setup_buffer[i] = usbd_sram[i];
buf += 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) {
uint32_t rxcnt;
USBOutEndpointState *oesp = usbp->epc[ep]->out_state;
if (oesp->rxsize > usbp->epc[ep]->out_maxsize) {
rxcnt = usbp->epc[ep]->out_maxsize;
}
else {
rxcnt = oesp->rxsize;
}
_toggle_dsq(oesp->hwEp, &(oesp->dsq));
USBD->EP[oesp->hwEp].MXPLD = rxcnt;
}
/**
* @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) {
uint32_t i, txcnt;
USBInEndpointState *iesp = usbp->epc[ep]->in_state;
if (iesp->txsize > usbp->epc[ep]->in_maxsize) {
txcnt = usbp->epc[ep]->in_maxsize;
}
else {
txcnt = iesp->txsize;
}
for (i = 0; i < txcnt; i++) {
usbd_sram[(USBD->EP[iesp->hwEp].BUFSEG) + i] = iesp->txbuf[i];
}
_toggle_dsq(iesp->hwEp, &(iesp->dsq));
USBD->EP[iesp->hwEp].MXPLD = txcnt;
}
/**
* @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) {
USBOutEndpointState *oesp = usbp->epc[ep]->out_state;
USBD->EP[oesp->hwEp].CFGP |= (USBD_CFGP_SSTALL_Msk | USBD_CFGP_CLRRDY_Msk);
}
/**
* @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) {
USBInEndpointState *iesp = usbp->epc[ep]->in_state;
USBD->EP[iesp->hwEp].CFGP |= (USBD_CFGP_SSTALL_Msk | USBD_CFGP_CLRRDY_Msk);
}
/**
* @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) {
USBOutEndpointState *oesp = usbp->epc[ep]->out_state;
USBD->EP[oesp->hwEp].CFGP &= ~USBD_CFGP_SSTALL_Msk;
}
/**
* @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) {
USBInEndpointState *iesp = usbp->epc[ep]->in_state;
USBD->EP[iesp->hwEp].CFGP &= ~USBD_CFGP_SSTALL_Msk;
}
#endif /* HAL_USE_USB == TRUE */
/** @} */

View File

@ -0,0 +1,425 @@
/*
ChibiOS - Copyright (C) 2017 Frank Zschockelt
ChibiOS - Copyright (C) 2019 /u/KeepItUnder
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 NUC123 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 8
/**
* @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 NUC123 configuration options
* @{
*/
/**
* @brief USB driver enable switch.
* @details If set to @p TRUE the support for USB1 is included.
* @note The default is @p FALSE.
*/
#if !defined(NUC123_USB_USE_USB1) || defined(__DOXYGEN__)
#define NUC123_USB_USE_USB1 FALSE
#endif
/**
* @brief USB interrupt priority level setting.
*/
#if !defined(NUC123_USB_USB1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NUC123_USB_USB1_IRQ_PRIORITY 2
#endif
/**
* @brief Host wake-up procedure duration.
*/
#if !defined(USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__)
#define USB_HOST_WAKEUP_DURATION 2
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (USB_HOST_WAKEUP_DURATION < 2) || (USB_HOST_WAKEUP_DURATION > 15)
#error "invalid USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15"
#endif
/*===========================================================================*/
/* 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.*/
uint8_t hwEp;
uint8_t dsq;
} 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.*/
uint8_t hwEp;
uint8_t dsq;
} 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.*/
uint32_t bufnext;
uint8_t epnext;
};
/*===========================================================================*/
/* 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) 0
/**
* @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) (USBD->ATTR |= USBD_ATTR_USB_EN_Msk | USBD_ATTR_PHY_EN_Msk)
/**
* @brief Disconnect the USB device.
*
* @api
*/
#define usb_lld_disconnect_bus(usbp) (USBD->ATTR &= ~USBD_ATTR_USB_EN_Msk)
/**
* @brief Start of host wake-up procedure.
*
* @notapi
*/
#define usb_lld_wakeup_host(usbp) \
do{ \
USBD->ATTR |= USBD_ATTR_RWAKEUP_Msk; \
osalThreadSleepMilliseconds(USB_HOST_WAKEUP_DURATION); \
USBD->ATTR &= ~USBD_ATTR_RWAKEUP_Msk; \
} while (false)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (NUC123_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,256 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 NUC123SD4AN0/hal_lld.c
* @brief NUC123SD4AN0 HAL subsystem low level driver source.
*
* @addtogroup HAL
* @{
*/
#include "hal.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define NUC123_PLLXTPRE_OFFSET 17 /**< PLLXTPRE offset */
#define NUC123_PLLXTPRE_MASK 0x01 /**< PLLXTPRE mask */
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief CMSIS system core clock variable.
* @note It is declared in system_NUC123SD4AN0.h.
*/
//uint32_t SystemCoreClock = NUC123_HCLK;
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if defined(NUC123_DMA_REQUIRED) || defined(__DOXYGEN__)
#if defined(NUC123_DMA1_CH23_HANDLER) || defined(__DOXYGEN__)
/**
* @brief DMA1 streams 2 and 3 shared ISR.
* @note It is declared here because this device has a non-standard
* DMA shared IRQ handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(NUC123_DMA1_CH23_HANDLER) {
OSAL_IRQ_PROLOGUE();
/* Check on channel 2.*/
dmaServeInterrupt(NUC123_DMA1_STREAM2);
/* Check on channel 3.*/
dmaServeInterrupt(NUC123_DMA1_STREAM3);
OSAL_IRQ_EPILOGUE();
}
#endif /* defined(NUC123_DMA1_CH23_HANDLER) */
#if defined(NUC123_DMA1_CH4567_HANDLER) || defined(__DOXYGEN__)
/**
* @brief DMA1 streams 4, 5, 6 and 7 shared ISR.
*
* @isr
*/
OSAL_IRQ_HANDLER(NUC123_DMA1_CH4567_HANDLER) {
OSAL_IRQ_PROLOGUE();
/* Check on channel 4.*/
dmaServeInterrupt(NUC123_DMA1_STREAM4);
/* Check on channel 5.*/
dmaServeInterrupt(NUC123_DMA1_STREAM5);
#if NUC123_DMA1_NUM_CHANNELS > 5
/* Check on channel 6.*/
dmaServeInterrupt(NUC123_DMA1_STREAM6);
#endif
#if NUC123_DMA1_NUM_CHANNELS > 6
/* Check on channel 7.*/
dmaServeInterrupt(NUC123_DMA1_STREAM7);
#endif
OSAL_IRQ_EPILOGUE();
}
#endif /* defined(NUC123_DMA1_CH4567_HANDLER) */
#if defined(NUC123_DMA12_CH23_CH12_HANDLER) || defined(__DOXYGEN__)
/**
* @brief DMA1 streams 2 and 3, DMA2 streams 1 and 1 shared ISR.
* @note It is declared here because this device has a non-standard
* DMA shared IRQ handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(NUC123_DMA12_CH23_CH12_HANDLER) {
OSAL_IRQ_PROLOGUE();
/* Check on channel 2 of DMA1.*/
dmaServeInterrupt(NUC123_DMA1_STREAM2);
/* Check on channel 3 of DMA1.*/
dmaServeInterrupt(NUC123_DMA1_STREAM3);
/* Check on channel 1 of DMA2.*/
dmaServeInterrupt(NUC123_DMA2_STREAM1);
/* Check on channel 2 of DMA2.*/
dmaServeInterrupt(NUC123_DMA2_STREAM2);
OSAL_IRQ_EPILOGUE();
}
#endif /* defined(NUC123_DMA12_CH23_CH12_HANDLER) */
#if defined(NUC123_DMA12_CH4567_CH345_HANDLER) || defined(__DOXYGEN__)
/**
* @brief DMA1 streams 4, 5, 6 and 7, DMA2 streams 3, 4 and 5 shared ISR.
* @note It is declared here because this device has a non-standard
* DMA shared IRQ handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(NUC123_DMA12_CH4567_CH345_HANDLER) {
OSAL_IRQ_PROLOGUE();
/* Check on channel 4 of DMA1.*/
dmaServeInterrupt(NUC123_DMA1_STREAM4);
/* Check on channel 5 of DMA1.*/
dmaServeInterrupt(NUC123_DMA1_STREAM5);
/* Check on channel 6 of DMA1.*/
dmaServeInterrupt(NUC123_DMA1_STREAM6);
/* Check on channel 7 of DMA1.*/
dmaServeInterrupt(NUC123_DMA1_STREAM7);
/* Check on channel 3 of DMA2.*/
dmaServeInterrupt(NUC123_DMA2_STREAM3);
/* Check on channel 4 of DMA2.*/
dmaServeInterrupt(NUC123_DMA2_STREAM4);
/* Check on channel 5 of DMA2.*/
dmaServeInterrupt(NUC123_DMA2_STREAM5);
OSAL_IRQ_EPILOGUE();
}
#endif /* defined(NUC123_DMA12_CH4567_CH345_HANDLER) */
#endif /* defined(NUC123_DMA_REQUIRED) */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level HAL driver initialization.
*
* @notapi
*/
void hal_lld_init(void) {
/* Reset of all peripherals.*/
// **NUC123TODO
#if defined(NUC123_DMA_REQUIRED)
//dmaInit();
//usbInit();
//uartInit();
//spiInit();
#endif
//usbInit();
}
/**
* @brief NUC123 clocks and PLL initialization.
* @note All the involved constants come from the file @p board.h.
* @note This function should be invoked just after the system reset.
*
* @special
*/
void NUC123_clock_init(void) {
SystemUnlockReg();
/* Enable XT1_OUT (PF.0) and XT1_IN (PF.1) */
SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable Internal RC 22.1184 MHz clock */
CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;
/* Waiting for Internal RC clock ready */
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
clks_lld_set_HCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
/* Enable external XTAL 12 MHz clock */
CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;
/* Waiting for external XTAL clock ready */
clks_lld_wait_for_clock_ready(CLK_CLKSTATUS_XTL12M_STB_Msk);
/* Set core clock */
clks_lld_set_core_clock(FREQ_72MHZ);
SystemCoreClock = NUC123_HCLK;
clks_lld_enable_SysTick(CLK_CLKSEL0_STCLK_S_HCLK_DIV2, (NUC123_HCLK / OSAL_ST_FREQUENCY) - 1);
/* Enable module clock */
clks_lld_enable_module_clock(USBD_ModuleNum);
/* Select module clock source */
clks_lld_set_module_clock(USBD_ModuleNum, 0, CLK_CLKDIV_USB(3));
/* TEMPORARY!!! */
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFP = (SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD);
/* Set PC.13 as CLKO function pin */
//SYS->GPC_MFP = SYS_GPC_MFP_PC13_CLKO;
//SYS->ALT_MFP = SYS_ALT_MFP_PC13_CLKO;
/* Enable CLKO (PC.13) for monitor HCLK. CLKO = HCLK/8 Hz*/
// clks_lld_enable_ck0(CLK_CLKSEL2_FRQDIV_S_HCLK, 2, 0);
LOCKREG();
}
/** @} */

View File

@ -0,0 +1,759 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 NUC123SD4AN0/hal_lld.h
* @brief NUC123SD4AN0 HAL subsystem low level driver header.
* @pre This module requires the following macros to be defined in the
* @p board.h file:
* - NUC123_LSECLK.
* - NUC123_LSEDRV.
* - NUC123_LSE_BYPASS (optionally).
* - NUC123_HSECLK.
* - NUC123_HSE_BYPASS (optionally).
* .
* .
*
* @addtogroup HAL
* @{
*/
#ifndef HAL_LLD_H
#define HAL_LLD_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Platform identification macros
* @{
*/
#if defined(NUC123SD4AN0) || defined(__DOXYGEN__)
#define PLATFORM_NAME "NUC123SD4AN0 NUC123 Cortex M0 USB Micro"
#else
#error "NUC123 device unsupported or not specified"
#endif
/** @} */
/**
* @name Absolute Maximum Ratings
* @{
*/
/**
* @brief Maximum system clock frequency.
*/
#define NUC123_SYSCLK_MAX FREQ_72MHZ
/**
* @brief Maximum HSE clock frequency.
*/
#define NUC123_HSECLK_MAX 24000000
/**
* @brief Minimum HSE clock frequency.
*/
#define NUC123_HSECLK_MIN 4000000
/**
* @brief Maximum LSE clock frequency.
*/
#define NUC123_LSECLK_MAX 10000
/**
* @brief Minimum LSE clock frequency.
*/
#define NUC123_LSECLK_MIN 10000
/**
* @brief Maximum PLLs input clock frequency.
*/
#define NUC123_PLLIN_MAX 24000000
/**
* @brief Minimum PLLs input clock frequency.
*/
#define NUC123_PLLIN_MIN 4000000
/**
* @brief Maximum PLL output clock frequency.
*/
#define NUC123_PLLOUT_MAX FREQ_72MHZ
/**
* @brief Minimum PLL output clock frequency.
*/
#define NUC123_PLLOUT_MIN 4000000
/**
* @brief Maximum APB clock frequency.
*/
#define NUC123_PCLK_MAX FREQ_72MHZ
/** @} */
/**
* @name Internal clock sources
* @{
*/
#define NUC123_HSICLK __HIRC /**< High speed internal clock. */
#define NUC123_HSI_69CLK 691200 /**< ~0.69MHz High speed internal clock. */
#define NUC123_HSI1_38CLK 1382400 /**< ~1.375MHz High speed internal clock. */
#define NUC123_HSI2_76CLK 2764800 /**< ~2.75MHz High speed internal clock. */
#define NUC123_HSI5_5CLK 5529600 /**< ~5.5MHz speed internal clock.*/
#define NUC123_HSI11CLK 11059200 /**< ~11MHz speed internal clock.*/
#define NUC123_LSICLK __LIRC /**< Low speed internal clock. */
/** @} */
/**
* @name CLKSEL0 register bits definitions
* @{
*/
#define NUC123_HCLKSRC_HSE (0 << 0) /**< HCLK source is HSE */
#define NUC123_HCLKSRC_PLL_2 (1 << 0) /**< HCLK source is PLL/2 */
#define NUC123_HCLKSRC_PLL (2 << 0) /**< HCLK source is PLL */
#define NUC123_HCLKSRC_LSI (3 << 0) /**< HCLK source is LSI */
#define NUC123_HCLKSRC_HSI (7 << 0) /**< HCLK source is HSI */
#define NUC123_SW_HSE (0 << 3) /**< SYSCLK source is HSE. */
#define NUC123_SW_HSE_2 (1 << 3) /**< SYSCLK source is HSE/2. */
#define NUC123_SW_HCLK_2 (3 << 3) /**< SYSCLK source is HCLK/2. */
#define NUC123_SW_HSI_2 (7 << 3) /**< SYSCLK source is HSI. */
/** @} */
/**
* @name CLKSEL1 register bits definitions
* @{
*/
#define NUC123_WDTSRC_MASK (3 << 0) /**< WDT source mask */
#define NUC123_WDTSRC_HCLK_2048 (2 << 0) /**< WDT source is HCLK/2048 */
#define NUC123_WDTSRC_LSI (3 << 0) /**< WDT source is LSI */
#define NUC123_ADCSRC_MASK (3 << 2) /**< ADC source mask */
#define NUC123_ADCSRC_HSE (0 << 2) /**< ADC source is HSE */
#define NUC123_ADCSRC_PLL (1 << 2) /**< ADC source is PLL */
#define NUC123_ADCSRC_HCLK (2 << 2) /**< ADC source is HCLK */
#define NUC123_ADCSRC_HSI (3 << 2) /**< ADC source is HSI */
#define NUC123_SPI0SRC_MASK (1 << 4) /**< SPI0 source mask */
#define NUC123_SPI0SRC_PLL (0 << 4) /**< SPI0 source is PLL */
#define NUC123_SPI0SRC_HCLK (1 << 4) /**< SPI0 source is HCLK */
#define NUC123_SPI1SRC_MASK (1 << 5) /**< SPI1 source MASK */
#define NUC123_SPI1SRC_PLL (0 << 5) /**< SPI1 source is PLL */
#define NUC123_SPI1SRC_HCLK (1 << 5) /**< SPI1 source is HCLK */
#define NUC123_SPI2SRC_MASK (1 << 6) /**< SPI2 source mask */
#define NUC123_SPI2SRC_PLL (0 << 6) /**< SPI2 source is PLL */
#define NUC123_SPI2SRC_HCLK (1 << 6) /**< SPI2 source is HCLK */
#define NUC123_TMR0SRC_MASK (7 << 8) /**< TMR0 source mask */
#define NUC123_TMR0SRC_HSE (0 << 8) /**< TMR0 source is HSE */
#define NUC123_TMR0SRC_HCLK (2 << 8) /**< TMR0 source is HCLK */
#define NUC123_TMR0SRC_TM0 (3 << 8) /**< TMR0 source is TM0 pin */
#define NUC123_TMR0SRC_LSI (5 << 8) /**< TMR0 source is LSI */
#define NUC123_TMR0SRC_HSI (7 << 8) /**< TMR0 source is HSI */
#define NUC123_TMR1SRC_MASK (7 << 12) /**< TMR1 source mask */
#define NUC123_TMR1SRC_HSE (0 << 12) /**< TMR1 source is HSE */
#define NUC123_TMR1SRC_HCLK (2 << 12) /**< TMR1 source is HCLK */
#define NUC123_TMR1SRC_TM1 (3 << 12) /**< TMR1 source is TM1 pin */
#define NUC123_TMR1SRC_LSI (5 << 12) /**< TMR1 source is LSI */
#define NUC123_TMR1SRC_HSI (7 << 12) /**< TMR1 source is HSI */
#define NUC123_TMR2SRC_MASK (7 << 16) /**< TMR2 source mask */
#define NUC123_TMR2SRC_HSE (0 << 16) /**< TMR2 source is HSE */
#define NUC123_TMR2SRC_HCLK (2 << 16) /**< TMR2 source is HCLK */
#define NUC123_TMR2SRC_TM2 (3 << 16) /**< TMR2 source is TM2 pin */
#define NUC123_TMR2SRC_LSI (5 << 16) /**< TMR2 source is LSI */
#define NUC123_TMR2SRC_HSI (7 << 16) /**< TMR2 source is HSI */
#define NUC123_TMR3SRC_MASK (7 << 20) /**< TMR3 source mask */
#define NUC123_TMR3SRC_HSE (0 << 20) /**< TMR3 source is HSE */
#define NUC123_TMR3SRC_HCLK (2 << 20) /**< TMR3 source is HCLK */
#define NUC123_TMR3SRC_LSI (5 << 20) /**< TMR3 source is LSI */
#define NUC123_TMR3SRC_HSI (7 << 20) /**< TMR3 source is HSI */
#define NUC123_USARTSRC_MASK (3 << 24) /**< UART source mask. */
#define NUC123_USARTSRC_HS3 (0 << 24) /**< UART source is HSE. */
#define NUC123_USARTSRC_PLL (1 << 24) /**< UART source is PLL. */
#define NUC123_USARTSRC_HSI (3 << 24) /**< UART source is HSI. */
#define NUC123_PWM01SRCA_MASK (3 << 28) /**< PWM0/1 source [1:0] mask */
#define NUC123_PWM01SRCA_HSE (0 << 28) /**< PWM0/1 source [1:0] is HSE */
#define NUC123_PWM01SRCA_HCLK (2 << 28) /**< PWM0/1 source [1:0] is HCLK*/
#define NUC123_PWM01SRCA_HSI (3 << 28) /**< PWM0/1 source [1:0] is HSI */
#define NUC123_PWM01SRCA_LSI (3 << 28) /**< PWM0/1 source [1:0] is LSI */
#define NUC123_PWM23SRCA_MASK (3 << 30) /**< PWM2/3 source [1:0] mask */
#define NUC123_PWM23SRCA_HSE (0 << 30) /**< PWM2/3 source [1:0] is HSE */
#define NUC123_PWM23SRCA_HCLK (2 << 30) /**< PWM2/3 source [1:0] is HCLK*/
#define NUC123_PWM23SRCA_HSI (3 << 30) /**< PWM2/3 source [1:0] is HSI */
#define NUC123_PWM23SRCA_LSI (3 << 30) /**< PWM2/3 source [1:0] is LSI */
/** @} */
/**
* @name CLKSEL2 register bits definitions
* @{
*/
#define NUC123_I2SSRC_MASK (3 << 0) /**< I2S clock source mask. */
#define NUC123_I2SSRC_HSE (0 << 0) /**< I2S clock source is HSE. */
#define NUC123_I2SSRC_PLL (1 << 0) /**< I2S clock source is PLL. */
#define NUC123_I2SSRC_HCLK (2 << 0) /**< I2S clock source is HCLK. */
#define NUC123_I2SSRC_HSI (3 << 0) /**< I2S clock source is HSI. */
#define NUC123_FREQDIVSRC_MASK (3 << 2) /**< FRQDIV clock source mask */
#define NUC123_FREQDIVSRC_HSE (0 << 2) /**< FRQDIV clock source is HSE */
#define NUC123_FREQDIVSRC_HCLK (2 << 2) /**< FRQDIV clock source is HCLK*/
#define NUC123_FREQDIVSRC_HSI (3 << 2) /**< FRQDIV clock source is LSI */
#define NUC123_PWM01SRCB_MASK (1 << 8) /**< PWM0/1 source [2] mask */
#define NUC123_PWM01SRCB_HSI (0 << 8) /**< PWM0/1 source [2] is HSI */
#define NUC123_PWM01SRCB_LSI (1 << 8) /**< PWM0/1 source [2] is LSI */
#define NUC123_PWM23SRCB_MASK (1 << 9) /**< PWM2/3 source [2] mask */
#define NUC123_PWM23SRCB_HSI (0 << 9) /**< PWM2/3 source [2] is HSI */
#define NUC123_PWM23SRCB_LSI (1 << 9) /**< PWM2/3 source [2] is LSI */
#define NUC123_WWDTSRC_MASK (3 << 16) /**< WWDT source mask */
#define NUC123_WWDTSRC_HCLK_2048 (2 << 16) /**< WWDT source is HCLK/2048 */
#define NUC123_WWDTSRC_LSI (3 << 16) /**< WWDT source is LSI */
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief Disables the PWR/RCC initialization in the HAL.
*/
#if !defined(NUC123_NO_INIT) || defined(__DOXYGEN__)
#define NUC123_NO_INIT FALSE
#endif
/**
* @brief Enables or disables the HSI clock source.
*/
#if !defined(NUC123_HSI_ENABLED) || defined(__DOXYGEN__)
#define NUC123_HSI_ENABLED TRUE
#endif
/**
* @brief Enables or disables the LSI clock source.
*/
#if !defined(NUC123_LSI_ENABLED) || defined(__DOXYGEN__)
#define NUC123_LSI_ENABLED TRUE
#endif
/**
* @brief Enables or disables the HSE clock source.
*/
#if !defined(NUC123_HSE_ENABLED) || defined(__DOXYGEN__)
#define NUC123_HSE_ENABLED TRUE
#endif
/**
* @brief Enables or disables the LSE clock source.
*/
#if !defined(NUC123_LSE_ENABLED) || defined(__DOXYGEN__)
#define NUC123_LSE_ENABLED FALSE
#endif
/**
* @brief Main clock source selection.
* @note If the selected clock source is not the PLL then the PLL is not
* initialized and started.
* @note The default value is calculated for a 72MHz system clock from
* a 12MHz crystal using the PLL.
*/
#if !defined(NUC123_SW) || defined(__DOXYGEN__)
#define NUC123_SW NUC123_SW_HCLK_2
#endif
/**
* @brief Clock source for the PLL.
* @note This setting has only effect if the PLL is selected as the
* system clock source.
* @note The default value is calculated for a 72MHz system clock from
* a 12MHz crystal using the PLL.
*/
#if !defined(NUC123_PLLSRC) || defined(__DOXYGEN__)
#define NUC123_PLLSRC NUC123_PLLSRC_HSE
#endif
/**
* @brief Crystal PLL pre-divider.
* @note This setting has only effect if the PLL is selected as the
* system clock source.
* @note The default value is calculated for a 72MHz system clock from
* a 21MHz crystal using the PLL.
*/
#if !defined(NUC123_PREDIV_VALUE) || defined(__DOXYGEN__)
#define NUC123_PREDIV_VALUE 1
#endif
/**
* @brief PLL multiplier value.
* @note The allowed range is 2...16.
* @note The default value is calculated for a 72MHz system clock from
* a 12MHz crystal using the PLL.
*/
#if !defined(NUC123_PLLMUL_VALUE) || defined(__DOXYGEN__)
#define NUC123_PLLMUL_VALUE 6
#endif
/**
* @brief AHB prescaler value.
* @note The default value is calculated for a 72MHz system clock from
* a 12MHz crystal using the PLL.
*/
#if !defined(NUC123_HPRE) || defined(__DOXYGEN__)
#define NUC123_HPRE NUC123_HPRE_DIV1
#endif
/**
* @brief APB1 prescaler value.
*/
#if !defined(NUC123_PPRE) || defined(__DOXYGEN__)
#define NUC123_PPRE NUC123_PPRE_DIV1
#endif
/**
* @brief MCO pin setting.
*/
#if !defined(NUC123_MCOSEL) || defined(__DOXYGEN__)
#define NUC123_MCOSEL NUC123_MCOSEL_NOCLOCK
#endif
/**
* @brief MCO divider setting.
*/
#if !defined(NUC123_MCOPRE) || defined(__DOXYGEN__)
#define NUC123_MCOPRE NUC123_MCOPRE_DIV1
#endif
/**
* @brief MCO PLL divider setting.
*/
#if !defined(NUC123_PLLNODIV) || defined(__DOXYGEN__)
#define NUC123_PLLNODIV NUC123_PLLNODIV_DIV2
#endif
/**
* @brief USB Clock source.
*/
#if !defined(NUC123_USBSW) || defined(__DOXYGEN__)
#define NUC123_USBSW NUC123_USBSW_HSI48
#endif
/**
* @brief CEC clock source.
*/
#if !defined(NUC123_CECSW) || defined(__DOXYGEN__)
#define NUC123_CECSW NUC123_CECSW_HSI
#endif
/**
* @brief I2C1 clock source.
*/
#if !defined(NUC123_I2C1SW) || defined(__DOXYGEN__)
#define NUC123_I2C1SW NUC123_I2C1SW_HSI
#endif
/**
* @brief USART1 clock source.
*/
#if !defined(NUC123_USART1SW) || defined(__DOXYGEN__)
#define NUC123_USART1SW NUC123_USART1SW_PCLK
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*
* Configuration-related checks.
*/
#if !defined(NUC123SD4AN0_MCUCONF)
#error "Using a wrong mcuconf.h file, NUC123SD4AN0_MCUCONF not defined"
#endif
/*
* HSI related checks.
*/
#if NUC123_HSI_ENABLED
/*#if NUC123_SW == NUC123_SW_HSE
#error "HSI not enabled, required by NUC123_SW"
#endif
#if NUC123_CECSW == NUC123_CECSW_HSI
#error "HSI not enabled, required by NUC123_CECSW"
#endif
#if NUC123_I2C1SW == NUC123_I2C1SW_HSI
#error "HSI not enabled, required by NUC123_I2C1SW"
#endif
#if NUC123_USART1SW == NUC123_USART1SW_HSI
#error "HSI not enabled, required by NUC123_USART1SW"
#endif
#if (NUC123_SW == NUC123_SW_PLL) && \
(NUC123_PLLSRC == NUC123_PLLSRC_HSI_DIV2) || \
(NUC123_PLLSRC == NUC123_PLLSRC_HSI)
#error "HSI not enabled, required by NUC123_SW and NUC123_PLLSRC"
#endif
#if (NUC123_MCOSEL == NUC123_MCOSEL_HSI) || \
((NUC123_MCOSEL == NUC123_MCOSEL_PLLDIV2) && \
((NUC123_PLLSRC == NUC123_PLLSRC_HSI_DIV2) || \
(NUC123_PLLSRC == NUC123_PLLSRC_HSI)))
#error "HSI not enabled, required by NUC123_MCOSEL"
#endif
*/
#endif /* !NUC123_HSI_ENABLED */
/*
* HSE related checks.
*/
#if NUC123_HSE_ENABLED
#if NUC123_HSECLK == 0
#error "HSE frequency not defined"
#elif (NUC123_HSECLK < NUC123_HSECLK_MIN) || (NUC123_HSECLK > NUC123_HSECLK_MAX)
#error "NUC123_HSECLK outside acceptable range (NUC123_HSECLK_MIN...NUC123_HSECLK_MAX)"
#endif
#else /* !NUC123_HSE_ENABLED */
#if (NUC123_SW == NUC123_SW_HSE) || (NUC123_SW == NUC123_SW_HSE_2)
#error "HSE not enabled, required by NUC123_SW"
#endif
#if (NUC123_SW == NUC123_SW_HCL) && (NUC123_PLLSRC == NUC123_PLLSRC_HSE)
#error "HSE not enabled, required by NUC123_SW and NUC123_PLLSRC"
#endif
#if (NUC123_MCOSEL == NUC123_MCOSEL_HSE) || \
((NUC123_MCOSEL == NUC123_MCOSEL_PLLDIV2) && \
(NUC123_PLLSRC == NUC123_PLLSRC_HSE))
#error "HSE not enabled, required by NUC123_MCOSEL"
#endif
#endif /* !NUC123_HSE_ENABLED */
/*
* LSI related checks.
*/
#if NUC123_LSI_ENABLED
#else /* !NUC123_LSI_ENABLED */
#if NUC123_RTCSEL == NUC123_RTCSEL_LSI
#error "LSI not enabled, required by NUC123_RTCSEL"
#endif
#endif /* !NUC123_LSI_ENABLED */
/*
* LSE related checks.
*/
#if NUC123_LSE_ENABLED
#if (NUC123_LSECLK == 0)
#error "LSE frequency not defined"
#endif
#if (NUC123_LSECLK < NUC123_LSECLK_MIN) || (NUC123_LSECLK > NUC123_LSECLK_MAX)
#error "NUC123_LSECLK outside acceptable range (NUC123_LSECLK_MIN...NUC123_LSECLK_MAX)"
#endif
#if !defined(NUC123_LSEDRV)
#error "NUC123_LSEDRV not defined"
#endif
#if (NUC123_LSEDRV >> 3) > 3
#error "NUC123_LSEDRV outside acceptable range ((0<<3)...(3<<3))"
#endif
#else /* !NUC123_LSE_ENABLED */
#endif /* !NUC123_LSE_ENABLED */
/* PLL activation conditions.*/
#if (NUC123_SW == NUC123_SW_PLL) || \
(NUC123_USBSW == NUC123_USBSW_PCLK) || \
(NUC123_MCOSEL == NUC123_MCOSEL_PLLDIV2) || \
defined(__DOXYGEN__)
/**
* @brief PLL activation flag.
*/
#define NUC123_ACTIVATE_PLL TRUE
#else
#define NUC123_ACTIVATE_PLL FALSE
#endif
/* HSE, HSI prescaler setting check.*/
#if ((NUC123_PREDIV_VALUE >= 1) || (NUC123_PREDIV_VALUE <= 16))
#define NUC123_PREDIV ((NUC123_PREDIV_VALUE - 1) << 0)
#else
#error "invalid NUC123_PREDIV value specified"
#endif
/**
* @brief PLLMUL field.
*/
#if ((NUC123_PLLMUL_VALUE >= 2) && (NUC123_PLLMUL_VALUE <= 16)) || \
defined(__DOXYGEN__)
#define NUC123_PLLMUL ((NUC123_PLLMUL_VALUE - 2) << 18)
#else
#error "invalid NUC123_PLLMUL_VALUE value specified"
#endif
/**
* @brief PLL input clock frequency.
*/
#if (NUC123_PLLSRC == NUC123_PLLSRC_HSE) || defined(__DOXYGEN__)
#define NUC123_PLLCLKIN (NUC123_HSECLK / NUC123_PREDIV_VALUE)
#elif NUC123_PLLSRC == NUC123_PLLSRC_HSI_DIV2
#define NUC123_PLLCLKIN (NUC123_HSICLK / 2)
#elif NUC123_PLLSRC == NUC123_PLLSRC_HSI
#define NUC123_PLLCLKIN (NUC123_HSICLK / NUC123_PREDIV_VALUE)
#else
#error "invalid NUC123_PLLSRC value specified"
#endif
/* PLL input frequency range check.*/
#if (NUC123_PLLCLKIN < NUC123_PLLIN_MIN) || (NUC123_PLLCLKIN > NUC123_PLLIN_MAX)
#error "NUC123_PLLCLKIN outside acceptable range (NUC123_PLLIN_MIN...NUC123_PLLIN_MAX)"
#endif
/**
* @brief PLL output clock frequency.
*/
#define NUC123_PLLCLKOUT (NUC123_PLLCLKIN * NUC123_PLLMUL_VALUE)
/* PLL output frequency range check.
#if (NUC123_PLLCLKOUT < NUC123_PLLOUT_MIN) || (NUC123_PLLCLKOUT > NUC123_PLLOUT_MAX)
#error "NUC123_PLLCLKOUT outside acceptable range (NUC123_PLLOUT_MIN...NUC123_PLLOUT_MAX)"
#endif
*/
/**
* @brief System clock source.
*/
#if (NUC123_SW == NUC123_SW_HSE) || defined(__DOXYGEN__)
#define NUC123_SYSCLK NUC123_HSECLK
#elif (NUC123_SW == NUC123_SW_HSE_2)
#define NUC123_SYSCLK NUC123_HSECLK >> 1
#elif (NUC123_SW == NUC123_SW_HCLK_2)
#define NUC123_SYSCLK FREQ_72MHZ >> 1
#elif (NUC123_SW == NUC123_SW_HSI_2)
#define NUC123_SYSCLK NUC123_HSI11CLK
#else
#error "invalid NUC123_SW value specified"
#endif
/* Check on the system clock.*/
#if NUC123_SYSCLK > NUC123_SYSCLK_MAX
#error "NUC123_SYSCLK above maximum rated frequency (NUC123_SYSCLK_MAX)"
#endif
/**
* @brief AHB frequency.
*
#if (NUC123_HPRE == NUC123_HPRE_DIV1) || defined(__DOXYGEN__)
#define NUC123_HCLK (NUC123_SYSCLK / 1)
#elif NUC123_HPRE == NUC123_HPRE_DIV2
#define NUC123_HCLK (NUC123_SYSCLK / 2)
#elif NUC123_HPRE == NUC123_HPRE_DIV4
#define NUC123_HCLK (NUC123_SYSCLK / 4)
#elif NUC123_HPRE == NUC123_HPRE_DIV8
#define NUC123_HCLK (NUC123_SYSCLK / 8)
#elif NUC123_HPRE == NUC123_HPRE_DIV16
#define NUC123_HCLK (NUC123_SYSCLK / 16)
#elif NUC123_HPRE == NUC123_HPRE_DIV64
#define NUC123_HCLK (NUC123_SYSCLK / 64)
#elif NUC123_HPRE == NUC123_HPRE_DIV128
#define NUC123_HCLK (NUC123_SYSCLK / 128)
#elif NUC123_HPRE == NUC123_HPRE_DIV256
#define NUC123_HCLK (NUC123_SYSCLK / 256)
#elif NUC123_HPRE == NUC123_HPRE_DIV512
#define NUC123_HCLK (NUC123_SYSCLK / 512)
#else
#error "invalid NUC123_HPRE value specified"
#endif
*/
#define NUC123_HCLK (NUC123_SYSCLK / 1)
/* AHB frequency check.*/
#if NUC123_HCLK > NUC123_SYSCLK_MAX
#error "NUC123_HCLK exceeding maximum frequency (NUC123_SYSCLK_MAX)"
#endif
/**
* @brief APB frequency.
*/
#if (NUC123_PPRE == NUC123_PPRE_DIV1) || defined(__DOXYGEN__)
#define NUC123_PCLK (NUC123_HCLK / 1)
#elif NUC123_PPRE == NUC123_PPRE_DIV2
#define NUC123_PCLK (NUC123_HCLK / 2)
#elif NUC123_PPRE == NUC123_PPRE_DIV4
#define NUC123_PCLK (NUC123_HCLK / 4)
#elif NUC123_PPRE == NUC123_PPRE_DIV8
#define NUC123_PCLK (NUC123_HCLK / 8)
#elif NUC123_PPRE == NUC123_PPRE_DIV16
#define NUC123_PCLK (NUC123_HCLK / 16)
#else
#error "invalid NUC123_PPRE value specified"
#endif
/* APB frequency check.*/
#if NUC123_PCLK > NUC123_PCLK_MAX
#error "NUC123_PCLK exceeding maximum frequency (NUC123_PCLK_MAX)"
#endif
/* NUC123_PLLNODIV check.*/
#if (NUC123_PLLNODIV != NUC123_PLLNODIV_DIV2) && \
(NUC123_PLLNODIV != NUC123_PLLNODIV_DIV1)
#error "invalid NUC123_PLLNODIV value specified"
#endif
/**
* @brief CEC frequency.
*/
#if (NUC123_CECSW == NUC123_CECSW_HSI) || defined(__DOXYGEN__)
#define NUC123_CECCLK NUC123_HSICLK
#elif NUC123_CECSW == NUC123_CECSW_LSE
#define NUC123_CECCLK NUC123_LSECLK
#elif NUC123_CECSW == NUC123_CECSW_OFF
#define NUC123_CECCLK 0
#else
#error "invalid source selected for CEC clock"
#endif
/**
* @brief I2C1 frequency.
*/
#if (NUC123_I2C1SW == NUC123_I2C1SW_HSI) || defined(__DOXYGEN__)
#define NUC123_I2C1CLK NUC123_HSICLK
#elif NUC123_I2C1SW == NUC123_I2C1SW_SYSCLK
#define NUC123_I2C1CLK NUC123_SYSCLK
#else
#error "invalid source selected for I2C1 clock"
#endif
/**
* @brief USART1 frequency.
*/
#if (NUC123_USART1SW == NUC123_USART1SW_PCLK) || defined(__DOXYGEN__)
#define NUC123_USART1CLK NUC123_PCLK
#elif NUC123_USART1SW == NUC123_USART1SW_SYSCLK
#define NUC123_USART1CLK NUC123_SYSCLK
#elif NUC123_USART1SW == NUC123_USART1SW_LSE
#define NUC123_USART1CLK NUC123_LSECLK
#elif NUC123_USART1SW == NUC123_USART1SW_HSI
#define NUC123_USART1CLK NUC123_HSICLK
#else
#error "invalid source selected for USART1 clock"
#endif
// /**
// * @brief USART2 frequency.
// */
// #define NUC123_USART2CLK NUC123_PCLK
// /**
// * @brief USART3 frequency.
// */
// #define NUC123_USART3CLK NUC123_PCLK
// /**
// * @brief USART4 frequency.
// */
// #define NUC123_UART4CLK NUC123_PCLK
// /**
// * @brief USART5 frequency.
// */
// #define NUC123_UART5CLK NUC123_PCLK
// /**
// * @brief USART6 frequency.
// */
// #define NUC123_USART6CLK NUC123_PCLK
/**
* @brief Timers clock.
*/
#if (NUC123_PPRE == NUC123_PPRE_DIV1) || defined(__DOXYGEN__)
#define NUC123_TIMCLK1 (NUC123_PCLK * 1)
#define NUC123_TIMCLK2 (NUC123_PCLK * 1)
#else
#define NUC123_TIMCLK1 (NUC123_PCLK * 2)
#define NUC123_TIMCLK2 (NUC123_PCLK * 2)
#endif
/**
* @brief Flash settings.
*/
#if (NUC123_HCLK <= 24000000) || defined(__DOXYGEN__)
#define NUC123_FLASHBITS 0x00000010
#else
#define NUC123_FLASHBITS 0x00000011
#endif
/*
* For compatibility with driver assuming a specific PPRE clock.
*/
#define NUC123_PCLK1 NUC123_PCLK
#define NUC123_PCLK2 NUC123_PCLK
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/* Various helpers.*/
#include "nvic.h"
#include "nuc123_isr.h"
//#include "nuc123_dma.h"
#include "hal_clks_lld.h"
#include "hal_pwm_lld.h"
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void NUC123_clock_init(void);
#ifdef __cplusplus
}
#endif
#endif /* HAL_LLD_H */
/** @} */

View File

@ -0,0 +1,152 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 NUMICRO/nuc123_isr.h
* @brief ISR remapper driver header.
*
* @addtogroup NUC123SD4AN0_ISR
* @{
*/
#ifndef NUC123_ISR_H
#define NUC123_ISR_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name ISR names and numbers remapping
* @{
*/
/*
* GPIO units.
*/
#if defined(NUC123SD4AN0)
#define NUC123_GPIOAB_HANDLER Vector50
#define NUC123_GPIOCDF_HANDLER Vector54
#define NUC123_GPIOAB_NUMBER GPAB_IRQn
#define NUC123_GPIOCDF_NUMBER GPCDF_IRQn
#endif
/*
* Special ST unit
*/
#define NUC123_ST_HANDLER Vector3C
#define NUC123_ST_NUMBER SysTick_IRQn
/*
* DMA units.
*/
#define NUC123_PDMA_HANDLER VectorA8
#define NUC123_PDMA_NUMBER PDMA_IRQn
/*
* ADC units.
*/
#define NUC123_ADC_HANDLER VectorB0
#define NUC123_ADC_NUMBER ADC_IRQn
/*
* PWM units.
*/
#define NUC123_PWMA_HANDLER Vector58
#define NUC123_PWMA_NUMBER PWMA_IRQn
/*
* SPI units.
*/
#define NUC123_SPI0_HANDLER Vector78
#define NUC123_SPI1_HANDLER Vector7C
#define NUC123_SPI2_HANDLER Vector80
#define NUC123_SPI0_NUMBER SPI0_IRQn
#define NUC123_SPI1_NUMBER SPI1_IRQn
#define NUC123_SPI2_NUMBER SPI2_IRQn
/*
* I2S units.
*/
#define NUC123_I2C1_HANDLER VectorB8
#define NUC123_I2C1_NUMBER I2S_IRQn
/*
* I2C units.
*/
#define NUC123_I2C1_GLOBAL_HANDLER Vector88
#define NUC123_I2C1_GLOBAL_NUMBER I2C0_IRQn
#define NUC123_I2C2_GLOBAL_HANDLER Vector8C
#define NUC123_I2C2_GLOBAL_NUMBER I2C1_IRQn
/*
* TIM units.
*/
#define NUC123_TIM1_HANDLER Vector60
#define NUC123_TIM2_HANDLER Vector64
#define NUC123_TIM3_HANDLER Vector68
#define NUC123_TIM4_HANDLER Vector6C
#define NUC123_TIM1_NUMBER TMR0_IRQn
#define NUC123_TIM2_NUMBER TMR1_IRQn
#define NUC123_TIM3_NUMBER TMR2_IRQn
#define NUC123_TIM4_NUMBER TMR3_IRQn
/*
* USART units.
*/
#define NUC123_USART1_HANDLER Vector70
#define NUC123_USART2_HANDLER Vector74
#define NUC123_USART1_NUMBER UART0_IRQn
#define NUC123_USART2_NUMBER UART1_IRQn
/*
* USB units.
*/
#define NUC123_USB1_HANDLER Vector9C
#define NUC123_USB1_NUMBER USBD_IRQn
#define USBD_INTSTS_EPEVT_Pos USBD_INTSTS_EPEVT0_Pos
#define USBD_INTSTS_EPEVT_Msk (0xFFul << USBD_INTSTS_EPEVT_Pos)
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#endif /* NUC123_ISR_H */
/** @} */

View File

@ -0,0 +1,263 @@
/*
Copyright (C) 2019 /u/KeepItUnder
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 NUC123SD4AN0/nuc123_registry.h
* @brief NUC123SD4AN0 capabilities registry.
*
* @addtogroup HAL
* @{
*/
#ifndef NUC123_REGISTRY_H
#define NUC123_REGISTRY_H
#if !defined(NUC123SD4AN0) || defined(__DOXYGEN__)
#define NUC123SD4AN0
#endif
/*===========================================================================*/
/* Platform capabilities. */
/*===========================================================================*/
/**
* @name NUC123SD4AN0 capabilities
* @{
*/
/* RCC attributes. */
#define NUC123_HAS_HSI48 FALSE
#define NUC123_HAS_HSI_PREDIV FALSE
#define NUC123_HAS_MCO_PREDIV TRUE
/* ADC attributes.*/
#define NUC123_HAS_ADC1 TRUE
#define NUC123_ADC_SUPPORTS_PRESCALER FALSE
#define NUC123_ADC_SUPPORTS_OVERSAMPLING FALSE
#define NUC123_ADC1_IRQ_SHARED_WITH_EXTI FALSE
#define NUC123_ADC1_HANDLER Vector70
#define NUC123_ADC1_NUMBER Vector70_IRQn
#define NUC123_ADC1_DMA_MSK (NUC123_DMA_STREAM_ID_MSK(1, 1) |\
NUC123_DMA_STREAM_ID_MSK(1, 2))
#define NUC123_ADC1_DMA_CHN 0x00000011
#define NUC123_HAS_ADC2 FALSE
#define NUC123_HAS_ADC3 FALSE
#define NUC123_HAS_ADC4 FALSE
/* CAN attributes.*/
#define NUC123_HAS_CAN1 FALSE
#define NUC123_HAS_CAN2 FALSE
#define NUC123_HAS_CAN3 FALSE
/* DAC attributes.*/
#define NUC123_HAS_DAC1_CH1 FALSE
#define NUC123_HAS_DAC1_CH2 FALSE
#define NUC123_HAS_DAC2_CH1 FALSE
#define NUC123_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/
#define NUC123_ADVANCED_DMA FALSE
#define NUC123_DMA_SUPPORTS_CSELR FALSE
#define NUC123_DMA1_NUM_CHANNELS 6
#define NUC123_DMA2_NUM_CHANNELS 0
#define NUC123_DMA1_CH1_HANDLER Vector64
#define NUC123_DMA1_CH23_HANDLER Vector68
#define NUC123_DMA1_CH4567_HANDLER Vector6C
#define NUC123_DMA1_CH1_NUMBER Vector64_IRQn
#define NUC123_DMA1_CH23_NUMBER Vector68_IRQn
#define NUC123_DMA1_CH4567_NUMBER Vector6C_IRQn
#define NUC123_DMA1_CH2_NUMBER NUC123_DMA1_CH23_NUMBER
#define NUC123_DMA1_CH3_NUMBER NUC123_DMA1_CH23_NUMBER
#define DMA1_CH2_CMASK 0x00000006U
#define DMA1_CH3_CMASK 0x00000006U
#define NUC123_DMA1_CH4_NUMBER NUC123_DMA1_CH4567_NUMBER
#define NUC123_DMA1_CH5_NUMBER NUC123_DMA1_CH4567_NUMBER
#define NUC123_DMA1_CH6_NUMBER NUC123_DMA1_CH4567_NUMBER
#define NUC123_DMA1_CH7_NUMBER NUC123_DMA1_CH4567_NUMBER
#define DMA1_CH4_CMASK 0x00000078U
#define DMA1_CH5_CMASK 0x00000078U
#define DMA1_CH6_CMASK 0x00000078U
#define DMA1_CH7_CMASK 0x00000078U
/* ETH attributes.*/
#define NUC123_HAS_ETH FALSE
/* EXTI attributes.*/
//#define NUC123_EXTI_NUM_LINES 20
//#define NUC123_EXTI_IMR_MASK 0xFFF50000U
/* GPIO attributes.*/
#define NUC123_HAS_GPIOA TRUE
#define NUC123_HAS_GPIOB TRUE
#define NUC123_HAS_GPIOC TRUE
#define NUC123_HAS_GPIOD TRUE
#define NUC123_HAS_GPIOE FALSE
#define NUC123_HAS_GPIOF TRUE
#define NUC123_HAS_GPIOG FALSE
#define NUC123_HAS_GPIOH FALSE
#define NUC123_HAS_GPIOI FALSE
#define NUC123_HAS_GPIOJ FALSE
#define NUC123_HAS_GPIOK FALSE
/* I2C attributes.*/
#define NUC123_HAS_I2C1 TRUE
#define NUC123_I2C1_RX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 3)
#define NUC123_I2C1_RX_DMA_CHN 0x00000200
#define NUC123_I2C1_TX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 2)
#define NUC123_I2C1_TX_DMA_CHN 0x00000020
#define NUC123_HAS_I2C2 TRUE
#define NUC123_I2C2_RX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 5)
#define NUC123_I2C2_RX_DMA_CHN 0x00020000
#define NUC123_I2C2_TX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 4)
#define NUC123_I2C2_TX_DMA_CHN 0x00002000
#define NUC123_HAS_I2C3 FALSE
#define NUC123_HAS_I2C4 FALSE
/* QUADSPI attributes.*/
#define NUC123_HAS_QUADSPI1 FALSE
/* RTC attributes.*/
#define NUC123_HAS_RTC FALSE
#define NUC123_RTC_HAS_SUBSECONDS FALSE
#define NUC123_RTC_HAS_PERIODIC_WAKEUPS FALSE
#define NUC123_RTC_NUM_ALARMS 0
#define NUC123_RTC_HAS_INTERRUPTS FALSE
/* SDIO attributes.*/
#define NUC123_HAS_SDIO FALSE
/* SPI attributes.*/
#define NUC123_HAS_SPI1 TRUE
#define NUC123_SPI1_SUPPORTS_I2S FALSE
#define NUC123_SPI1_RX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 2)
#define NUC123_SPI1_RX_DMA_CHN 0x00000030
#define NUC123_SPI1_TX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 3)
#define NUC123_SPI1_TX_DMA_CHN 0x00000300
#define NUC123_HAS_SPI2 TRUE
#define NUC123_SPI2_SUPPORTS_I2S FALSE
#define NUC123_SPI2_RX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 4)
#define NUC123_SPI2_RX_DMA_CHN 0x00003000
#define NUC123_SPI2_TX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 5)
#define NUC123_SPI2_TX_DMA_CHN 0x00030000
#define NUC123_HAS_SPI3 FALSE
#define NUC123_HAS_SPI4 FALSE
#define NUC123_HAS_SPI5 FALSE
#define NUC123_HAS_SPI6 FALSE
/* TIM attributes.*/
#define NUC123_TIM_MAX_CHANNELS 4
#define NUC123_HAS_TIM1 TRUE
#define NUC123_TIM1_IS_32BITS TRUE
#define NUC123_TIM1_CHANNELS 1
#define NUC123_HAS_TIM2 TRUE
#define NUC123_TIM2_IS_32BITS TRUE
#define NUC123_TIM2_CHANNELS 1
#define NUC123_HAS_TIM3 TRUE
#define NUC123_TIM3_IS_32BITS TRUE
#define NUC123_TIM3_CHANNELS 1
#define NUC123_HAS_TIM4 TRUE
#define NUC123_TIM14_IS_32BITS TRUE
#define NUC123_TIM14_CHANNELS 1
#define NUC123_HAS_TIM5 FALSE
#define NUC123_HAS_TIM6 FALSE
#define NUC123_HAS_TIM7 FALSE
#define NUC123_HAS_TIM8 FALSE
#define NUC123_HAS_TIM9 FALSE
#define NUC123_HAS_TIM10 FALSE
#define NUC123_HAS_TIM11 FALSE
#define NUC123_HAS_TIM12 FALSE
#define NUC123_HAS_TIM13 FALSE
#define NUC123_HAS_TIM14 FALSE
#define NUC123_HAS_TIM15 FALSE
#define NUC123_HAS_TIM16 FALSE
#define NUC123_HAS_TIM17 FALSE
#define NUC123_HAS_TIM18 FALSE
#define NUC123_HAS_TIM19 FALSE
#define NUC123_HAS_TIM20 FALSE
#define NUC123_HAS_TIM21 FALSE
#define NUC123_HAS_TIM22 FALSE
/* USART attributes.*/
/*#define NUC123_HAS_USART1 TRUE
#define NUC123_USART1_RX_DMA_MSK (NUC123_DMA_STREAM_ID_MSK(1, 1) |\
NUC123_DMA_STREAM_ID_MSK(1, 3) |\
NUC123_DMA_STREAM_ID_MSK(1, 5))
#define NUC123_USART1_RX_DMA_CHN 0x00080808
#define NUC123_USART1_TX_DMA_MSK (NUC123_DMA_STREAM_ID_MSK(1, 2) |\
NUC123_DMA_STREAM_ID_MSK(1, 4))
#define NUC123_USART1_TX_DMA_CHN 0x00008080
#define NUC123_HAS_USART2 TRUE
#define NUC123_USART2_RX_DMA_MSK (NUC123_DMA_STREAM_ID_MSK(1, 1) |\
NUC123_DMA_STREAM_ID_MSK(1, 3) |\
NUC123_DMA_STREAM_ID_MSK(1, 5))
#define NUC123_USART2_RX_DMA_CHN 0x00090909
#define NUC123_USART2_TX_DMA_MSK (NUC123_DMA_STREAM_ID_MSK(1, 2) |\
NUC123_DMA_STREAM_ID_MSK(1, 4))
#define NUC123_USART2_TX_DMA_CHN 0x00009090
*/
#define NUC123_HAS_USART1 FALSE
#define NUC123_HAS_USART2 FALSE
#define NUC123_HAS_USART3 FALSE
#define NUC123_HAS_UART4 FALSE
#define NUC123_HAS_UART5 FALSE
#define NUC123_HAS_USART6 FALSE
#define NUC123_HAS_UART7 FALSE
#define NUC123_HAS_UART8 FALSE
#define NUC123_HAS_LPUART1 FALSE
/* USB attributes.*/
#define NUC123_HAS_USB TRUE
#define NUC123_HAS_OTG1 FALSE
#define NUC123_HAS_OTG2 FALSE
/* IWDG attributes.*/
#define NUC123_HAS_IWDG TRUE
#define NUC123_IWDG_IS_WINDOWED TRUE
/* LTDC attributes.*/
#define NUC123_HAS_LTDC FALSE
/* DMA2D attributes.*/
#define NUC123_HAS_DMA2D FALSE
/* FSMC attributes.*/
#define NUC123_HAS_FSMC FALSE
/* CRC attributes.*/
#define NUC123_HAS_CRC TRUE
#define NUC123_CRC_PROGRAMMABLE FALSE
#else
#error "NUC123SD4AN0 device not specified"
/** @} */
#endif /* NUC123_REGISTRY_H */
/** @} */

View File

@ -0,0 +1,21 @@
# Required platform files.
PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
$(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/NUC123SD4AN0/hal_lld.c \
$(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/NUC123SD4AN0/system_NUC123SD4AN0.c
# Required include directories.
PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \
$(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/NUC123SD4AN0 \
$(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD
# Optional platform files.
ifeq ($(USE_SMART_BUILD),yes)
HALCONF := $(strip $(shell cat halconf.h | egrep -e "\#define"))
endif
# Drivers compatible with the platform.
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/CLKv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/GPIOv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/USBv1/driver.mk

View File

@ -0,0 +1,153 @@
/**************************************************************************//**
* @file system_NUC123SD4AN0.c
* @brief CMSIS Cortex-M0 Device Peripheral Access Layer Source File for
* Device NUC123SD4AN0
* @version V5.00
* @date 13. May 2019
******************************************************************************/
/*
* Copyright (c) 2019 /u/KeepItUnder. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* 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 <stdint.h>
#include "NUC123SD4AN0.h"
/*----------------------------------------------------------------------------
Define clocks
*----------------------------------------------------------------------------*/
/* ToDo: add here your necessary defines for device initialization
following is an example for different system frequencies */
// #define XTAL (12000000U) /* Oscillator frequency */
// #define SYSTEM_CLOCK (5 * XTAL)
/*----------------------------------------------------------------------------
System Core Clock Variable
*----------------------------------------------------------------------------*/
/* ToDo: initialize SystemCoreClock with the system core clock frequency value
achieved after system intitialization.
This means system core clock frequency after call to SystemInit() */
// uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Clock Frequency (Core Clock)*/
// uint32_t CyclesPerUs = (SYSTEM_CLOCK / 1000000); /* Cycles per micro second */
// uint32_t PllClock = SYSTEM_CLOCK; /*!< PLL Clock Frequency */
uint32_t SystemCoreClock = __HSI; /* System Clock Frequency (Core Clock)*/
uint32_t CyclesPerUs = (__HSI / 1000000); /* Cycles per micro second */
uint32_t PllClock = __HSI; /*!< PLL Clock Frequency */
/*----------------------------------------------------------------------------
Clock functions
*----------------------------------------------------------------------------*/
void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
{
/* ToDo: add code to calculate the system frequency based upon the current
register settings.
This function can be used to retrieve the system core clock frequeny
after user changed register sittings. */
// SystemCoreClock = SYSTEM_CLOCK;
uint32_t clkFreq;
uint32_t PllReg;
uint32_t pllFIN, pllNF, pllNR, pllNO;
/* Update PLL Clock */
// PllClock = clks_lld_get_pll_clock_freq();
PllReg = CLK->PLLCON;
if(PllReg & (CLK_PLLCON_PD_Msk | CLK_PLLCON_OE_Msk)) {
PllClock = 0; /* PLL is off. */
} else {
if (PllReg & 0x00080000ul) {
pllFIN = __HIRC; /* Use HXT for PLL clock */
} else {
pllFIN = __HXT; /* Use HXT for PLL clock */
}
if (PllReg & CLK_PLLCON_BP_Msk) {
PllClock = pllFIN;
} else {
switch (((PllReg & CLK_PLLCON_OUT_DV_Msk) >> CLK_PLLCON_OUT_DV_Pos)) {
case 0b00: /* OUT_DIV == 00 : NO = 1 */
pllNO = 1;
break;
case 0b11: /* OUT_DIV == 11 : NO = 4 */
pllNO = 4;
break;
default: /* OUT_DIV == 01 or 10 : NO = 2 */
pllNO = 2;
break;
}
pllNF = ((PllReg & CLK_PLLCON_FB_DV_Msk) >> CLK_PLLCON_FB_DV_Pos) + 2;
pllNR = ((PllReg & CLK_PLLCON_IN_DV_Msk) >> CLK_PLLCON_IN_DV_Pos) + 2;
/* Shift right to avoid overflow condition */
PllClock = (((pllFIN >> 2) * pllNF) / (pllNR * pllNO) << 2);
}
}
/* Pick Clock Source */
switch (CLK->CLKSEL0 & CLK_CLKSEL0_HCLK_S_Msk) {
case 0: // External HF Xtal
clkFreq = __HXT;
break;
case 1: // PLL clock / 2
clkFreq = PllClock >> 1;
break;
case 3: // Internal 10kHz
clkFreq = __LIRC;
break;
case 2: // PLL clock
clkFreq = PllClock;
break;
case 7: // Internal 22.184MHz
clkFreq = __HIRC;
break;
default:
clkFreq = NULL;
break;
}
SystemCoreClock = clkFreq / ((CLK->CLKDIV & CLK_CLKDIV_HCLK_N_Msk) + 1);
// CyclesPerUs = (SystemCoreClock + 500000) / 1000000;
CyclesPerUs = SystemCoreClock / 1000000;
}
void SystemInit (void)
{
/* ToDo: add code to initialize the system
do not use global variables because this function is called before
reaching pre-main. RW section maybe overwritten afterwards. */
// SystemCoreClock = SYSTEM_CLOCK;
}
void SystemUnlockReg(void)
{
while(SYS->REGWRPROT != SYS_REGWRPROT_REGPROTDIS_Msk)
{
SYS->REGWRPROT = 0x59ul;
SYS->REGWRPROT = 0x16ul;
SYS->REGWRPROT = 0x88ul;
}
}