diff --git a/source/hic_hal/nxp/lpc4322/RTE_Device.h b/source/hic_hal/nxp/lpc4322/RTE_Device.h index 48bdb7fdc..fd75c3642 100644 --- a/source/hic_hal/nxp/lpc4322/RTE_Device.h +++ b/source/hic_hal/nxp/lpc4322/RTE_Device.h @@ -1010,12 +1010,12 @@ // I2C1 (Inter-integrated Circuit Interface 1) [Driver_I2C1] // USART0 (Universal synchronous asynchronous receiver transmitter) [Driver_USART0] -#define RTE_USART0 0 +#define RTE_USART0 1 // Pin Configuration // TX <0=>Not used <1=>P2_0 <2=>P6_4 <3=>P9_5 <4=>PF_10 // USART0 Serial Output pin -#define RTE_USART0_TX_ID 0 +#define RTE_USART0_TX_ID 1 #if (RTE_USART0_TX_ID == 0) #define RTE_USART0_TX_PIN_EN 0 #elif (RTE_USART0_TX_ID == 1) @@ -1042,7 +1042,7 @@ #endif // RX <0=>Not used <1=>P2_1 <2=>P6_5 <3=>P9_6 <4=>PF_11 // USART0 Serial Input pin -#define RTE_USART0_RX_ID 0 +#define RTE_USART0_RX_ID 1 #if (RTE_USART0_RX_ID == 0) #define RTE_USART0_RX_PIN_EN 0 #elif (RTE_USART0_RX_ID == 1) diff --git a/source/hic_hal/nxp/lpc4322/board_LPC43xx.c b/source/hic_hal/nxp/lpc4322/board_LPC43xx.c index 367366f58..2ae946aeb 100644 --- a/source/hic_hal/nxp/lpc4322/board_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/board_LPC43xx.c @@ -20,24 +20,7 @@ */ #include "sdk.h" -#include "lpc43xx_cgu.h" void sdk_init(void) { - /* Set core clock to 120MHz */ - CGU_Init(120000000); - /* Set up USB0 clock */ - /* Disable PLL first */ - CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); - - /* the usb core require output clock = 480MHz */ - if (CGU_SetPLL0() != CGU_ERROR_SUCCESS) { - while (1); - } - - CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0); - /* Enable PLL after all setting is done */ - CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE); - /* Turn on the USB0PHY */ - LPC_CREG->CREG0 &= ~(1 << 5); } diff --git a/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.c b/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.c deleted file mode 100644 index 867cc2fb4..000000000 --- a/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.c +++ /dev/null @@ -1,1132 +0,0 @@ -/** - * @file lpc43xx_cgu.c - * @brief - * - * DAPLink Interface Firmware - * Copyright (c) 2009-2016, ARM Limited, 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "lpc_types.h" -#include "lpc43xx_scu.h" -#include "lpc43xx_cgu.h" - -/** This define used to fix mistake when run with IAR compiler */ -#ifdef __ICCARM__ -#define CGU_BRANCH_STATUS_ENABLE_MASK 0x80000001 -#else -#define CGU_BRANCH_STATUS_ENABLE_MASK 0x01 -#endif - -/*TODO List: - * SET PLL0 - * UPDATE Clock from PLL0 - * SetDIV uncheck value - * GetBaseStatus BASE_SAFE - * */ -/* Local definition */ -#define CGU_ADDRESS32(x,y) (*(uint32_t*)((uint32_t)x+y)) - -/* Local Variable */ -const int16_t CGU_Entity_ControlReg_Offset[CGU_ENTITY_NUM] = { - -1, //CGU_CLKSRC_32KHZ_OSC, - -1, //CGU_CLKSRC_IRC, - -1, //CGU_CLKSRC_ENET_RX_CLK, - -1, //CGU_CLKSRC_ENET_TX_CLK, - -1, //CGU_CLKSRC_GP_CLKIN, - -1, //CGU_CLKSRC_TCK, - 0x18, //CGU_CLKSRC_XTAL_OSC, - 0x20, //CGU_CLKSRC_PLL0, - 0x30, //CGU_CLKSRC_PLL0_AUDIO **REV A** - 0x44, //CGU_CLKSRC_PLL1, - -1, //CGU_CLKSRC_RESERVE, - -1, //CGU_CLKSRC_RESERVE, - 0x48, //CGU_CLKSRC_IDIVA,, - 0x4C, //CGU_CLKSRC_IDIVB, - 0x50, //CGU_CLKSRC_IDIVC, - 0x54, //CGU_CLKSRC_IDIVD, - 0x58, //CGU_CLKSRC_IDIVE, - - 0x5C, //CGU_BASE_SAFE, - 0x60, //CGU_BASE_USB0, - 0x64, //CGU_BASE_PERIPH, // used for SPGPIO, peripheral control - 0x68, //CGU_BASE_USB1, - 0x6C, //CGU_BASE_M4, - 0x70, //CGU_BASE_SPIFI, - -1, //CGU_BASE_RESERVE, - 0x78, //CGU_BASE_PHY_RX, - 0x7C, //CGU_BASE_PHY_TX, - 0x80, //CGU_BASE_APB1, - 0x84, //CGU_BASE_APB3, - 0x88, //CGU_BASE_LCD, - 0X8C, //CGU_BASE_ENET_CSR, **REV A** - 0x90, //CGU_BASE_SDIO, - 0x94, //CGU_BASE_SSP0, - 0x98, //CGU_BASE_SSP1, - 0x9C, //CGU_BASE_UART0, - 0xA0, //CGU_BASE_UART1, - 0xA4, //CGU_BASE_UART2, - 0xA8, //CGU_BASE_UART3, - 0xAC, //CGU_BASE_CLKOUT - -1, - -1, - -1, - -1, - 0xC0, //CGU_BASE_APLL - 0xC4, //CGU_BASE_OUT0 - 0xC8 //CGU_BASE_OUT1 -}; - -const uint8_t CGU_ConnectAlloc_Tbl[CGU_CLKSRC_NUM][CGU_ENTITY_NUM] = { -// 3 I E E G T X P P P x x D D D D D S U P U M S x P P A A L E S S S U U U U C x x x x A O O -// 2 R R T P C T L L L I I I I I A S E S 3 P H H P P C N D S S R R R R O P U U -// C X X I K A 0 A 1 A B C D E F B R B F RxTx1 3 D T I 0 1 0 1 2 3 L T T - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_32KHZ_OSC = 0,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_IRC,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_ENET_RX_CLK,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_ENET_TX_CLK,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_GP_CLKIN,*/ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, /*CGU_CLKSRC_TCK,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_XTAL_OSC,*/ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1}, /*CGU_CLKSRC_PLL0,*/ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_PLL0_AUDIO,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_PLL1,*/ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_IDIVA = CGU_CLKSRC_PLL1 + 3,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_IDIVB,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_IDIVC,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, /*CGU_CLKSRC_IDIVD,*/ - {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1} /*CGU_CLKSRC_IDIVE,*/ -}; - -const CGU_PERIPHERAL_S CGU_PERIPHERAL_Info[CGU_PERIPHERAL_NUM] = { - /* Register Clock | Peripheral Clock - | BASE | BRANCH | BASE | BRANCH */ - {CGU_BASE_APB3, 0x1118, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_ADC0, - {CGU_BASE_APB3, 0x1120, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_ADC1, - {CGU_BASE_M4, 0x1460, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_AES, - //// CGU_PERIPHERAL_ALARMTIMER_CGU_RGU_RTC_WIC, - {CGU_BASE_APB1, 0x1200, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_APB1_BUS, - {CGU_BASE_APB3, 0x1100, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_APB3_BUS, - {CGU_BASE_APB3, 0x1128, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_CAN0, - {CGU_BASE_M4, 0x1538, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_CREG, - {CGU_BASE_APB3, 0x1110, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_DAC, - {CGU_BASE_M4, 0x1440, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_DMA, - {CGU_BASE_M4, 0x1430, CGU_BASE_M4, 0x1478, 0},//CGU_PERIPHERAL_EMC, - {CGU_BASE_M4, 0x1420, CGU_BASE_PHY_RX, 0x0000, CGU_PERIPHERAL_ETHERNET_TX},//CGU_PERIPHERAL_ETHERNET, - {CGU_ENTITY_NONE, 0x0000, CGU_BASE_PHY_TX, 0x0000, 0}, //CGU_PERIPHERAL_ETHERNET_TX - {CGU_BASE_M4, 0x1410, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_GPIO, - {CGU_BASE_APB1, 0x1210, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_I2C0, - {CGU_BASE_APB3, 0x1108, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_I2C1, - {CGU_BASE_APB1, 0x1218, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_I2S, - {CGU_BASE_M4, 0x1418, CGU_BASE_LCD, 0x0000, 0},//CGU_PERIPHERAL_LCD, - {CGU_BASE_M4, 0x1448, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_M3CORE, - {CGU_BASE_M4, 0x1400, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_M3_BUS, - {CGU_BASE_APB1, 0x1208, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_MOTOCON, - {CGU_BASE_M4, 0x1630, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_QEI, - {CGU_BASE_M4, 0x1600, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_RITIMER, - {CGU_BASE_M4, 0x1468, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_SCT, - {CGU_BASE_M4, 0x1530, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_SCU, - {CGU_BASE_M4, 0x1438, CGU_BASE_SDIO, 0x2800, 0},//CGU_PERIPHERAL_SDIO, - {CGU_BASE_M4, 0x1408, CGU_BASE_SPIFI, 0x1300, 0},//CGU_PERIPHERAL_SPIFI, - {CGU_BASE_M4, 0x1518, CGU_BASE_SSP0, 0x2700, 0},//CGU_PERIPHERAL_SSP0, - {CGU_BASE_M4, 0x1628, CGU_BASE_SSP1, 0x2600, 0},//CGU_PERIPHERAL_SSP1, - {CGU_BASE_M4, 0x1520, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER0, - {CGU_BASE_M4, 0x1528, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER1, - {CGU_BASE_M4, 0x1618, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER2, - {CGU_BASE_M4, 0x1620, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER3, - {CGU_BASE_M4, 0x1508, CGU_BASE_UART0, 0x2500, 0},//CGU_PERIPHERAL_UART0, - {CGU_BASE_M4, 0x1510, CGU_BASE_UART1, 0x2400, 0},//CGU_PERIPHERAL_UART1, - {CGU_BASE_M4, 0x1608, CGU_BASE_UART2, 0x2300, 0},//CGU_PERIPHERAL_UART2, - {CGU_BASE_M4, 0x1610, CGU_BASE_UART3, 0x2200, 0},//CGU_PERIPHERAL_UART3, - {CGU_BASE_M4, 0x1428, CGU_BASE_USB0, 0x1800, 0},//CGU_PERIPHERAL_USB0, - {CGU_BASE_M4, 0x1470, CGU_BASE_USB1, 0x1900, 0},//CGU_PERIPHERAL_USB1, - {CGU_BASE_M4, 0x1500, CGU_BASE_SAFE, 0x0000, 0},//CGU_PERIPHERAL_WWDT, -}; - -uint32_t CGU_ClockSourceFrequency[CGU_CLKSRC_NUM] = {0, 12000000, 0, 0, 0, 0, 0, 480000000, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -#define CGU_CGU_ADDR ((uint32_t)LPC_CGU) -#define CGU_REG_BASE_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_Entity_ControlReg_Offset[CGU_PERIPHERAL_Info[x].RegBaseEntity])) -#define CGU_REG_BRANCH_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].RegBranchOffset)) -#define CGU_REG_BRANCH_STATUS(x) (*(volatile uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].RegBranchOffset+4)) - -#define CGU_PER_BASE_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_Entity_ControlReg_Offset[CGU_PERIPHERAL_Info[x].PerBaseEntity])) -#define CGU_PER_BRANCH_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].PerBranchOffset)) -#define CGU_PER_BRANCH_STATUS(x) (*(volatile uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].PerBranchOffset+4)) - -/**************************************************************************//** - * - * @brief Rough approximation of a delay function with microsecond resolution. - * - * Used during initial clock setup as the Timers are not configured yet. - * - * @param [in] us The number of microseconds to wait - * - *****************************************************************************/ -static void cgu_WaitUS(volatile uint32_t us) -{ - us *= (SystemCoreClock / 1000000) / 3; - - while (us--); -} - -/**************************************************************************//** - * - * @brief Simple lookup of best MSEL and NSEL values for wanted frequency - * - * Not optimized. - * - * @param [in] wantedFreq The wanted PLL1 frequency - * @param [out] pMsel The best MSEL value for the PLL1_CTRL register - * @param [out] pNsel The best NSEL value for the PLL1_CTRL register - * - *****************************************************************************/ -static void cgu_findMN(uint32_t wantedFreq, uint32_t *pMsel, uint32_t *pNsel) -{ - uint32_t besterr = wantedFreq; - uint32_t m, n, f, tmp, err; -#define ABSDIFF(__a, __b) ( ((__a) < (__b)) ? ((__b) - (__a)) : ((__a) - (__b)) ) - - for (n = 1; n <= 4; n++) { - f = 12000000 / n; - tmp = 0; - - for (m = 1; m <= 256; m++) { - tmp += f; - err = ABSDIFF(tmp, wantedFreq); - - if (err == 0) { - // found perfect match - *pMsel = m - 1; - *pNsel = n - 1; - return; - - } else if (err < besterr) { - *pMsel = m - 1; - *pNsel = n - 1; - besterr = err; - } - - if (tmp > wantedFreq) { - // no point in continuing to increase tmp as value is too high already - break; - } - } - } -} - -/*********************************************************************//** - * @brief Initialize default clock for LPC4300 Eval board - * @param[in] None - * @return Initialize status, could be: - * - CGU_ERROR_SUCCESS: successful - * - Other: error - **********************************************************************/ -uint32_t CGU_Init(uint32_t wantedFreq) -{ - uint32_t msel = 0; - uint32_t nsel = 0; - uint32_t tmp; - // Setup PLL1 to 204MHz - // 0. Select IRC as BASE_M4_CLK source - CGU_EntityConnect(CGU_CLKSRC_IRC, CGU_BASE_M4); - SystemCoreClock = 120000000; - // 1. Enable the crystal oscillator - CGU_SetXTALOSC(12000000); - CGU_EnableEntity(CGU_CLKSRC_XTAL_OSC, ENABLE); - // 2. Wait 250us - cgu_WaitUS(250); - // 3. Reconfigure PLL1 as follows: - // - Select the M and N divider values to produce the final desired - // PLL1 output frequency (204MHz => M=17,N=1 => msel=16,nsel=0) - // - Select the crystal oscillator as clock source for PLL1 - cgu_findMN(wantedFreq, &msel, &nsel); - tmp = LPC_CGU->PLL1_CTRL & ~((0xFF << 16) | (0x03 << 12)); - LPC_CGU->PLL1_CTRL = tmp | (msel << 16) | (nsel << 12); - CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL1); - - // 4. Wait for the PLL1 to lock - while ((LPC_CGU->PLL1_STAT & 1) == 0x0); - - // 5. Set PLL1 P-divider to divide by 2 (DIRECT=0 and PSEL=0) - LPC_CGU->PLL1_CTRL &= ~((0x03 << 8) | CGU_PLL1_DIRECT_MASK); - // 6. Select PLL1 as BASE_M4_CLK source. The BASE_M4_CLK now operates at - // the mid frequency range - CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4); - SystemCoreClock = (12000000 * (msel + 1)) / ((nsel + 1) * 2); - // 7. Wait 20us - cgu_WaitUS(20); - // 8. Set PLL P-divider to direct output mode (DIRECT=1) - LPC_CGU->PLL1_CTRL |= CGU_PLL1_DIRECT_MASK; - // The BASE_M4_CLK now operates in the high frequency range - CGU_UpdateClock(); - SystemCoreClock = (12000000 * (msel + 1)) / (nsel + 1); - return 0; -} - -/*********************************************************************//** - * @brief Configure power for individual peripheral - * @param[in] PPType peripheral type, should be: - * - CGU_PERIPHERAL_ADC0 :ADC0 - * - CGU_PERIPHERAL_ADC1 :ADC1 - * - CGU_PERIPHERAL_AES :AES - * - CGU_PERIPHERAL_APB1_BUS :APB1 bus - * - CGU_PERIPHERAL_APB3_BUS :APB3 bus - * - CGU_PERIPHERAL_CAN :CAN - * - CGU_PERIPHERAL_CREG :CREG - * - CGU_PERIPHERAL_DAC :DAC - * - CGU_PERIPHERAL_DMA :DMA - * - CGU_PERIPHERAL_EMC :EMC - * - CGU_PERIPHERAL_ETHERNET :ETHERNET - * - CGU_PERIPHERAL_GPIO :GPIO - * - CGU_PERIPHERAL_I2C0 :I2C0 - * - CGU_PERIPHERAL_I2C1 :I2C1 - * - CGU_PERIPHERAL_I2S :I2S - * - CGU_PERIPHERAL_LCD :LCD - * - CGU_PERIPHERAL_M3CORE :M3 core - * - CGU_PERIPHERAL_M3_BUS :M3 bus - * - CGU_PERIPHERAL_MOTOCON :Motor control - * - CGU_PERIPHERAL_QEI :QEI - * - CGU_PERIPHERAL_RITIMER :RIT timer - * - CGU_PERIPHERAL_SCT :SCT - * - CGU_PERIPHERAL_SCU :SCU - * - CGU_PERIPHERAL_SDIO :SDIO - * - CGU_PERIPHERAL_SPIFI :SPIFI - * - CGU_PERIPHERAL_SSP0 :SSP0 - * - CGU_PERIPHERAL_SSP1 :SSP1 - * - CGU_PERIPHERAL_TIMER0 :TIMER0 - * - CGU_PERIPHERAL_TIMER1 :TIMER1 - * - CGU_PERIPHERAL_TIMER2 :TIMER2 - * - CGU_PERIPHERAL_TIMER3 :TIMER3 - * - CGU_PERIPHERAL_UART0 :UART0 - * - CGU_PERIPHERAL_UART1 :UART1 - * - CGU_PERIPHERAL_UART2 :UART2 - * - CGU_PERIPHERAL_UART3 :UART3 - * - CGU_PERIPHERAL_USB0 :USB0 - * - CGU_PERIPHERAL_USB1 :USB1 - * - CGU_PERIPHERAL_WWDT :WWDT - * @param[in] en status, should be: - * - ENABLE: Enable power - * - DISABLE: Disable power - * @return Configure status, could be: - * - CGU_ERROR_SUCCESS: successful - * - Other: error - **********************************************************************/ -uint32_t CGU_ConfigPWR(CGU_PERIPHERAL_T PPType, FunctionalState en) -{ - if (PPType >= CGU_PERIPHERAL_WWDT && PPType <= CGU_PERIPHERAL_ADC0) { - return CGU_ERROR_INVALID_PARAM; - } - - if (en == DISABLE) { /* Going to disable clock */ - /*Get Reg branch status */ - if (CGU_PERIPHERAL_Info[PPType].RegBranchOffset != 0 && - CGU_REG_BRANCH_STATUS(PPType) & 1) { - CGU_REG_BRANCH_CTRL(PPType) &= ~1; /* Disable branch clock */ - - while (CGU_REG_BRANCH_STATUS(PPType) & 1); - } - - /* GetBase Status*/ - if ((CGU_PERIPHERAL_Info[PPType].RegBaseEntity != CGU_ENTITY_NONE) && - CGU_GetBaseStatus((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity) == 0) { - /* Disable Base */ - CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity, 0); - } - - /* Same for Peripheral */ - if ((CGU_PERIPHERAL_Info[PPType].PerBranchOffset != 0) && (CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)) { - CGU_PER_BRANCH_CTRL(PPType) &= ~1; /* Disable branch clock */ - - while (CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK); - } - - /* GetBase Status*/ - if ((CGU_PERIPHERAL_Info[PPType].PerBaseEntity != CGU_ENTITY_NONE) && - CGU_GetBaseStatus((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity) == 0) { - /* Disable Base */ - CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity, 0); - } - - } else { - /* enable */ - /* GetBase Status*/ - if ((CGU_PERIPHERAL_Info[PPType].RegBaseEntity != CGU_ENTITY_NONE) && CGU_REG_BASE_CTRL(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK) { - /* Enable Base */ - CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity, 1); - } - - /*Get Reg branch status */ - if ((CGU_PERIPHERAL_Info[PPType].RegBranchOffset != 0) && !(CGU_REG_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)) { - CGU_REG_BRANCH_CTRL(PPType) |= 1; /* Enable branch clock */ - - while (!(CGU_REG_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)); - } - - /* Same for Peripheral */ - /* GetBase Status*/ - if ((CGU_PERIPHERAL_Info[PPType].PerBaseEntity != CGU_ENTITY_NONE) && - (CGU_PER_BASE_CTRL(PPType) & 1)) { - /* Enable Base */ - CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity, 1); - } - - /*Get Reg branch status */ - if ((CGU_PERIPHERAL_Info[PPType].PerBranchOffset != 0) && !(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)) { - CGU_PER_BRANCH_CTRL(PPType) |= 1; /* Enable branch clock */ - - while (!(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)); - } - } - - if (CGU_PERIPHERAL_Info[PPType].next) { - return CGU_ConfigPWR((CGU_PERIPHERAL_T)CGU_PERIPHERAL_Info[PPType].next, en); - } - - return CGU_ERROR_SUCCESS; -} - - -/*********************************************************************//** - * @brief Get peripheral clock frequency - * @param[in] Clock Peripheral type, should be: - * - CGU_PERIPHERAL_ADC0 :ADC0 - * - CGU_PERIPHERAL_ADC1 :ADC1 - * - CGU_PERIPHERAL_AES :AES - * - CGU_PERIPHERAL_APB1_BUS :APB1 bus - * - CGU_PERIPHERAL_APB3_BUS :APB3 bus - * - CGU_PERIPHERAL_CAN :CAN - * - CGU_PERIPHERAL_CREG :CREG - * - CGU_PERIPHERAL_DAC :DAC - * - CGU_PERIPHERAL_DMA :DMA - * - CGU_PERIPHERAL_EMC :EMC - * - CGU_PERIPHERAL_ETHERNET :ETHERNET - * - CGU_PERIPHERAL_GPIO :GPIO - * - CGU_PERIPHERAL_I2C0 :I2C0 - * - CGU_PERIPHERAL_I2C1 :I2C1 - * - CGU_PERIPHERAL_I2S :I2S - * - CGU_PERIPHERAL_LCD :LCD - * - CGU_PERIPHERAL_M3CORE :M3 core - * - CGU_PERIPHERAL_M3_BUS :M3 bus - * - CGU_PERIPHERAL_MOTOCON :Motor control - * - CGU_PERIPHERAL_QEI :QEI - * - CGU_PERIPHERAL_RITIMER :RIT timer - * - CGU_PERIPHERAL_SCT :SCT - * - CGU_PERIPHERAL_SCU :SCU - * - CGU_PERIPHERAL_SDIO :SDIO - * - CGU_PERIPHERAL_SPIFI :SPIFI - * - CGU_PERIPHERAL_SSP0 :SSP0 - * - CGU_PERIPHERAL_SSP1 :SSP1 - * - CGU_PERIPHERAL_TIMER0 :TIMER0 - * - CGU_PERIPHERAL_TIMER1 :TIMER1 - * - CGU_PERIPHERAL_TIMER2 :TIMER2 - * - CGU_PERIPHERAL_TIMER3 :TIMER3 - * - CGU_PERIPHERAL_UART0 :UART0 - * - CGU_PERIPHERAL_UART1 :UART1 - * - CGU_PERIPHERAL_UART2 :UART2 - * - CGU_PERIPHERAL_UART3 :UART3 - * - CGU_PERIPHERAL_USB0 :USB0 - * - CGU_PERIPHERAL_USB1 :USB1 - * - CGU_PERIPHERAL_WWDT :WWDT - * @return Return frequently value - **********************************************************************/ -uint32_t CGU_GetPCLKFrequency(CGU_PERIPHERAL_T Clock) -{ - uint32_t ClkSrc; - - if (Clock >= CGU_PERIPHERAL_WWDT && Clock <= CGU_PERIPHERAL_ADC0) { - return CGU_ERROR_INVALID_PARAM; - } - - if (CGU_PERIPHERAL_Info[Clock].PerBaseEntity != CGU_ENTITY_NONE) { - /* Get Base Clock Source */ - ClkSrc = (CGU_PER_BASE_CTRL(Clock) & CGU_CTRL_SRC_MASK) >> 24; - - /* GetBase Status*/ - if (CGU_PER_BASE_CTRL(Clock) & 1) { - return 0; - } - - /* check Branch if it is enabled */ - if ((CGU_PERIPHERAL_Info[Clock].PerBranchOffset != 0) && !(CGU_PER_BRANCH_STATUS(Clock) & CGU_BRANCH_STATUS_ENABLE_MASK)) { - return 0; - } - - } else { - if (CGU_REG_BASE_CTRL(Clock) & 1) { - return 0; - } - - ClkSrc = (CGU_REG_BASE_CTRL(Clock) & CGU_CTRL_SRC_MASK) >> 24; - - /* check Branch if it is enabled */ - if ((CGU_PERIPHERAL_Info[Clock].RegBranchOffset != 0) && !(CGU_REG_BRANCH_STATUS(Clock) & CGU_BRANCH_STATUS_ENABLE_MASK)) { - return 0; - } - } - - return CGU_ClockSourceFrequency[ClkSrc]; -} - - -/*********************************************************************//** - * @brief Update clock - * @param[in] None - * @return None - **********************************************************************/ -void CGU_UpdateClock(void) -{ - uint32_t ClkSrc; - uint32_t div; - uint32_t divisor; - int32_t RegOffset; - - /* 32OSC */ - if (ISBITSET(LPC_CREG->CREG0, 1) && ISBITCLR(LPC_CREG->CREG0, 3)) { - CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 32768; - - } else { - CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 0; - } - - /*PLL0*/ - /* PLL1 */ - if (ISBITCLR(LPC_CGU->PLL1_CTRL, 0) /* Enabled */ /* EA ANDLI: Original code tested bit 1 which is BYPASS, not PD */ - && (LPC_CGU->PLL1_STAT & 1)) { /* Locked? */ - ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK) >> 24; - CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = CGU_ClockSourceFrequency[ClkSrc] * - (((LPC_CGU->PLL1_CTRL >> 16) & 0xFF) + 1); - - } else { - CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = 0; - } - - /* DIV */ - for (div = CGU_CLKSRC_IDIVA; div <= CGU_CLKSRC_IDIVE; div++) { - RegOffset = CGU_Entity_ControlReg_Offset[div]; - - if (ISBITCLR(CGU_ADDRESS32(LPC_CGU, RegOffset), 1)) { - ClkSrc = (CGU_ADDRESS32(LPC_CGU, RegOffset) & CGU_CTRL_SRC_MASK) >> 24; - divisor = (CGU_ADDRESS32(LPC_CGU, RegOffset) >> 2) & 0xFF; - divisor ++; - CGU_ClockSourceFrequency[div] = CGU_ClockSourceFrequency[ClkSrc] / divisor; - - } else { - CGU_ClockSourceFrequency[div] = 0; - } - } -} - -/*********************************************************************//** - * @brief Set XTAL oscillator value - * @param[in] ClockFrequency XTAL Frequency value - * @return Setting status, could be: - * - CGU_ERROR_SUCCESS: successful - * - CGU_ERROR_FREQ_OUTOF_RANGE: XTAL value set is out of range - **********************************************************************/ -uint32_t CGU_SetXTALOSC(uint32_t ClockFrequency) -{ - if (ClockFrequency < 15000000) { - LPC_CGU->XTAL_OSC_CTRL &= ~(1 << 2); - - } else if (ClockFrequency < 25000000) { - LPC_CGU->XTAL_OSC_CTRL |= (1 << 2); - - } else { - return CGU_ERROR_FREQ_OUTOF_RANGE; - } - - CGU_ClockSourceFrequency[CGU_CLKSRC_XTAL_OSC] = ClockFrequency; - return CGU_ERROR_SUCCESS; -} - - -/*********************************************************************//** - * @brief Set clock divider - * @param[in] SelectDivider Clock source, should be: - * - CGU_CLKSRC_IDIVA :Integer divider register A - * - CGU_CLKSRC_IDIVB :Integer divider register B - * - CGU_CLKSRC_IDIVC :Integer divider register C - * - CGU_CLKSRC_IDIVD :Integer divider register D - * - CGU_CLKSRC_IDIVE :Integer divider register E - * @param[in] divisor Divisor value, should be: 0..255 - * @return Setting status, could be: - * - CGU_ERROR_SUCCESS: successful - * - CGU_ERROR_INVALID_ENTITY: Invalid entity - **********************************************************************/ -/* divisor number must >=1*/ -uint32_t CGU_SetDIV(CGU_ENTITY_T SelectDivider, uint32_t divisor) -{ - int32_t RegOffset; - uint32_t tempReg; - - if (SelectDivider >= CGU_CLKSRC_IDIVA && SelectDivider <= CGU_CLKSRC_IDIVE) { - RegOffset = CGU_Entity_ControlReg_Offset[SelectDivider]; - - if (RegOffset == -1) { - return CGU_ERROR_INVALID_ENTITY; - } - - tempReg = CGU_ADDRESS32(LPC_CGU, RegOffset); - tempReg &= ~(0xFF << 2); - tempReg |= ((divisor - 1) & 0xFF) << 2; - CGU_ADDRESS32(LPC_CGU, RegOffset) = tempReg; - return CGU_ERROR_SUCCESS; - } - - return CGU_ERROR_INVALID_ENTITY; -} - -/*********************************************************************//** - * @brief Enable clock entity - * @param[in] ClockEntity Clock entity, should be: - * - CGU_CLKSRC_32KHZ_OSC :32Khz oscillator - * - CGU_CLKSRC_IRC :IRC clock - * - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock - * - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock - * - CGU_CLKSRC_GP_CLKIN :General purpose input clock - * - CGU_CLKSRC_XTAL_OSC :Crystal oscillator - * - CGU_CLKSRC_PLL0 :PLL0 clock - * - CGU_CLKSRC_PLL1 :PLL1 clock - * - CGU_CLKSRC_IDIVA :Integer divider register A - * - CGU_CLKSRC_IDIVB :Integer divider register B - * - CGU_CLKSRC_IDIVC :Integer divider register C - * - CGU_CLKSRC_IDIVD :Integer divider register D - * - CGU_CLKSRC_IDIVE :Integer divider register E - * - CGU_BASE_SAFE :Base safe clock (always on)for WDT - * - CGU_BASE_USB0 :Base clock for USB0 - * - CGU_BASE_PERIPH :Base clock for Peripheral bus - * - CGU_BASE_USB1 :Base clock for USB1 - * - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core - * and APB peripheral blocks #0 and #2 - * - CGU_BASE_SPIFI :Base clock for SPIFI - * - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx - * - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx - * - CGU_BASE_APB1 :Base clock for APB peripheral block #1 - * - CGU_BASE_APB3 :Base clock for APB peripheral block #3 - * - CGU_BASE_LCD :Base clock for LCD - * - CGU_BASE_SDIO :Base clock for SDIO card reader - * - CGU_BASE_SSP0 :Base clock for SSP0 - * - CGU_BASE_SSP1 :Base clock for SSP1 - * - CGU_BASE_UART0 :Base clock for UART0 - * - CGU_BASE_UART1 :Base clock for UART1 - * - CGU_BASE_UART2 :Base clock for UART2 - * - CGU_BASE_UART3 :Base clock for UART3 - * - CGU_BASE_CLKOUT :Base clock for CLKOUT pin - * @param[in] en status, should be: - * - ENABLE: Enable power - * - DISABLE: Disable power - * @return Setting status, could be: - * - CGU_ERROR_SUCCESS: successful - * - CGU_ERROR_INVALID_ENTITY: Invalid entity - **********************************************************************/ -uint32_t CGU_EnableEntity(CGU_ENTITY_T ClockEntity, uint32_t en) -{ - int32_t RegOffset; - int32_t i; - - if (ClockEntity == CGU_CLKSRC_32KHZ_OSC) { - if (en) { - LPC_CREG->CREG0 &= ~((1 << 3) | (1 << 2)); - LPC_CREG->CREG0 |= (1 << 1) | (1 << 0); - - } else { - LPC_CREG->CREG0 &= ~((1 << 1) | (1 << 0)); - LPC_CREG->CREG0 |= (1 << 3); - } - - for (i = 0; i < 1000000; i++); - - } else if (ClockEntity == CGU_CLKSRC_ENET_RX_CLK) { - scu_pinmux(0xC , 0 , MD_PLN, FUNC3); - - } else if (ClockEntity == CGU_CLKSRC_ENET_TX_CLK) { - scu_pinmux(0x1 , 19 , MD_PLN, FUNC0); - - } else if (ClockEntity == CGU_CLKSRC_GP_CLKIN) { - } else if (ClockEntity == CGU_CLKSRC_TCK) { - } else if (ClockEntity == CGU_CLKSRC_XTAL_OSC) { - if (!en) { - LPC_CGU->XTAL_OSC_CTRL |= CGU_CTRL_EN_MASK; - - } else { - LPC_CGU->XTAL_OSC_CTRL &= ~CGU_CTRL_EN_MASK; - } - - /*Delay for stable clock*/ - for (i = 0; i < 1000000; i++); - - } else { - RegOffset = CGU_Entity_ControlReg_Offset[ClockEntity]; - - if (RegOffset == -1) { - return CGU_ERROR_INVALID_ENTITY; - } - - if (!en) { - CGU_ADDRESS32(CGU_CGU_ADDR, RegOffset) |= CGU_CTRL_EN_MASK; - - } else { - CGU_ADDRESS32(CGU_CGU_ADDR, RegOffset) &= ~CGU_CTRL_EN_MASK; - - /*if PLL is selected check if it is locked */ - if (ClockEntity == CGU_CLKSRC_PLL0) { - while ((LPC_CGU->PLL0USB_STAT & 1) == 0x0); - } - - if (ClockEntity == CGU_CLKSRC_PLL0_AUDIO) { - while ((LPC_CGU->PLL0AUDIO_STAT & 1) == 0x0); - } - - if (ClockEntity == CGU_CLKSRC_PLL1) { - while ((LPC_CGU->PLL1_STAT & 1) == 0x0); - - /*post check lock status */ - if (!(LPC_CGU->PLL1_STAT & 1)) - while (1); - } - } - } - - return CGU_ERROR_SUCCESS; -} - -/*********************************************************************//** - * @brief Connect entity clock source - * @param[in] ClockSource Clock source, should be: - * - CGU_CLKSRC_32KHZ_OSC :32Khz oscillator - * - CGU_CLKSRC_IRC :IRC clock - * - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock - * - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock - * - CGU_CLKSRC_GP_CLKIN :General purpose input clock - * - CGU_CLKSRC_XTAL_OSC :Crystal oscillator - * - CGU_CLKSRC_PLL0 :PLL0 clock - * - CGU_CLKSRC_PLL1 :PLL1 clock - * - CGU_CLKSRC_IDIVA :Integer divider register A - * - CGU_CLKSRC_IDIVB :Integer divider register B - * - CGU_CLKSRC_IDIVC :Integer divider register C - * - CGU_CLKSRC_IDIVD :Integer divider register D - * - CGU_CLKSRC_IDIVE :Integer divider register E - * @param[in] ClockEntity Clock entity, should be: - * - CGU_CLKSRC_PLL0 :PLL0 clock - * - CGU_CLKSRC_PLL1 :PLL1 clock - * - CGU_CLKSRC_IDIVA :Integer divider register A - * - CGU_CLKSRC_IDIVB :Integer divider register B - * - CGU_CLKSRC_IDIVC :Integer divider register C - * - CGU_CLKSRC_IDIVD :Integer divider register D - * - CGU_CLKSRC_IDIVE :Integer divider register E - * - CGU_BASE_SAFE :Base safe clock (always on)for WDT - * - CGU_BASE_USB0 :Base clock for USB0 - * - CGU_BASE_USB1 :Base clock for USB1 - * - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core - * and APB peripheral blocks #0 and #2 - * - CGU_BASE_SPIFI :Base clock for SPIFI - * - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx - * - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx - * - CGU_BASE_APB1 :Base clock for APB peripheral block #1 - * - CGU_BASE_APB3 :Base clock for APB peripheral block #3 - * - CGU_BASE_LCD :Base clock for LCD - * - CGU_BASE_SDIO :Base clock for SDIO card reader - * - CGU_BASE_SSP0 :Base clock for SSP0 - * - CGU_BASE_SSP1 :Base clock for SSP1 - * - CGU_BASE_UART0 :Base clock for UART0 - * - CGU_BASE_UART1 :Base clock for UART1 - * - CGU_BASE_UART2 :Base clock for UART2 - * - CGU_BASE_UART3 :Base clock for UART3 - * - CGU_BASE_CLKOUT :Base clock for CLKOUT pin - * @return Setting status, could be: - * - CGU_ERROR_SUCCESS: successful - * - CGU_ERROR_CONNECT_TOGETHER: Error when 2 clock source connect together - * - CGU_ERROR_INVALID_CLOCK_SOURCE: Invalid clock source error - * - CGU_ERROR_INVALID_ENTITY: Invalid entity error - **********************************************************************/ -/* Connect one entity into clock source */ -uint32_t CGU_EntityConnect(CGU_ENTITY_T ClockSource, CGU_ENTITY_T ClockEntity) -{ - int32_t RegOffset; - uint32_t tempReg; - - if (ClockSource > CGU_CLKSRC_IDIVE) { - return CGU_ERROR_INVALID_CLOCK_SOURCE; - } - - if (ClockEntity >= CGU_CLKSRC_PLL0 && ClockEntity <= CGU_BASE_CLKOUT) { - if (CGU_ConnectAlloc_Tbl[ClockSource][ClockEntity]) { - RegOffset = CGU_Entity_ControlReg_Offset[ClockSource]; - - if (RegOffset != -1) { - if (ClockEntity <= CGU_CLKSRC_IDIVE && - ClockEntity >= CGU_CLKSRC_PLL0) { - //RegOffset = (CGU_ADDRESS32(LPC_CGU,RegOffset)>>24)&0xF; - if (((CGU_ADDRESS32(LPC_CGU, RegOffset) >> 24) & 0xF) == ClockEntity) { - return CGU_ERROR_CONNECT_TOGETHER; - } - } - } - - RegOffset = CGU_Entity_ControlReg_Offset[ClockEntity]; - - if (RegOffset == -1) { - return CGU_ERROR_INVALID_ENTITY; - } - - tempReg = CGU_ADDRESS32(LPC_CGU, RegOffset); - tempReg &= ~CGU_CTRL_SRC_MASK; - tempReg |= ClockSource << 24 | CGU_CTRL_AUTOBLOCK_MASK; - CGU_ADDRESS32(LPC_CGU, RegOffset) = tempReg; - return CGU_ERROR_SUCCESS; - - } else { - return CGU_ERROR_INVALID_CLOCK_SOURCE; - } - - } else { - return CGU_ERROR_INVALID_ENTITY; - } -} - - -/*********************************************************************//** - * @brief Get current USB PLL clock from XTAL - * @param[in] None - * @return Returned clock value - **********************************************************************/ -uint32_t CGU_SetPLL0(void) -{ - // Setup PLL550 to generate 480MHz from 12 MHz crystal - LPC_CGU->PLL0USB_CTRL |= 1; // Power down PLL - // P N - LPC_CGU->PLL0USB_NP_DIV = (98 << 0) | (514 << 12); - // SELP SELI SELR MDEC - LPC_CGU->PLL0USB_MDIV = (0xB << 17) | (0x10 << 22) | (0 << 28) | (0x7FFA << 0); - LPC_CGU->PLL0USB_CTRL = (CGU_CLKSRC_XTAL_OSC << 24) | (0x3 << 2) | (1 << 4); - return CGU_ERROR_SUCCESS; -} - - - -/*********************************************************************//** - * @brief Get current Audio PLL clock from XTAL - * @param[in] None - * @return Returned clock value - **********************************************************************/ -uint32_t CGU_SetPLL0audio(void) -{ - /* disable clock, disable skew enable, power down pll, - * (dis/en)able post divider, (dis/en)able pre-divider, - * disable free running mode, disable bandsel, - * enable up limmiter, disable bypass - */ - LPC_CGU->PLL0AUDIO_CTRL = (6 << 24) /* source = XTAL OSC 12 MHz */ - | _BIT(0); /* power down */ - /* PLL should be set to 512fs rate 512 * 48000 = 24576000 Hz */ - /* set mdec register */ -#if 1 // results from gcc program - LPC_CGU->PLL0AUDIO_MDIV = 0x23e34d3; - LPC_CGU->PLL0AUDIO_NP_DIV = 0x3f00e; - LPC_CGU->PLL0AUDIO_CTRL = (6 << 24) /* source = XTAL OSC 12 MHz */ - | (6 << 12) // fractional divider off and bypassed - | _BIT(4); /* CLKEN */ -#else - LPC_CGU->PLL0AUDIO_MDIV = (0 << 28) /* SELR */ - | (40 << 22) /* SELI */ - | (31 << 17) /* SELP */ - | 11372; /* MDEC */ - /* set ndec, pdec register */ - LPC_CGU->PLL0AUDIO_NP_DIV = (22 << 12) /* ndec */ - | (10); /* pdec */ - /* set fraction divider register. [21:15] = m, [14:0] = fractional value */ - LPC_CGU->PLL0AUDIO_FRAC = (86 << 15) | 0x1B7; - LPC_CGU->PLL0AUDIO_CTRL = (6 << 24) /* source = XTAL OSC 12 MHz */ - | _BIT(12) /* enable SD modulator to update mdec*/ - | _BIT(4); /* CLKEN */ -#endif - - /* wait for lock */ - while (!(LPC_CGU->PLL0AUDIO_STAT & 1)); - - return CGU_ERROR_SUCCESS; -} - - -/*********************************************************************//** - * @brief Setting PLL1 - * @param[in] mult Multiple value - * @return Setting status, could be: - * - CGU_ERROR_SUCCESS: successful - * - CGU_ERROR_INVALID_PARAM: Invalid parameter error - **********************************************************************/ -uint32_t CGU_SetPLL1(uint32_t mult) -{ - uint32_t msel = 0, nsel = 0, psel = 0, pval = 1; - uint32_t freq; - uint32_t ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK) >> 24; - freq = CGU_ClockSourceFrequency[ClkSrc]; - freq *= mult; - msel = mult - 1; - LPC_CGU->PLL1_CTRL &= ~(CGU_PLL1_FBSEL_MASK | - CGU_PLL1_BYPASS_MASK | - CGU_PLL1_DIRECT_MASK | - (0x03 << 8) | (0xFF << 16) | (0x03 << 12)); - - if (freq < 156000000) { - //psel is encoded such that 0=1, 1=2, 2=4, 3=8 - while (2 * (pval)*freq < 156000000) { - psel++; - pval *= 2; - } - -// if(2*(pval)*freq > 320000000) { -// //THIS IS OUT OF RANGE!!! -// //HOW DO WE ASSERT IN SAMPLE CODE? -// //__breakpoint(0); -// return CGU_ERROR_INVALID_PARAM; -// } - LPC_CGU->PLL1_CTRL |= (msel << 16) | (nsel << 12) | (psel << 8) | CGU_PLL1_FBSEL_MASK; - - } else if (freq < 320000000) { - LPC_CGU->PLL1_CTRL |= (msel << 16) | (nsel << 12) | (psel << 8) | CGU_PLL1_DIRECT_MASK | CGU_PLL1_FBSEL_MASK; - - } else { - return CGU_ERROR_INVALID_PARAM; - } - - return CGU_ERROR_SUCCESS; -} - - -/*********************************************************************//** - * @brief Get current base status - * @param[in] Base Base type, should be: - * - CGU_BASE_USB0 :Base clock for USB0 - * - CGU_BASE_USB1 :Base clock for USB1 - * - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core - * and APB peripheral blocks #0 and #2 - * - CGU_BASE_SPIFI :Base clock for SPIFI - * - CGU_BASE_APB1 :Base clock for APB peripheral block #1 - * - CGU_BASE_APB3 :Base clock for APB peripheral block #3 - * - CGU_BASE_SDIO :Base clock for SDIO card reader - * - CGU_BASE_SSP0 :Base clock for SSP0 - * - CGU_BASE_SSP1 :Base clock for SSP1 - * - CGU_BASE_UART0 :Base clock for UART0 - * - CGU_BASE_UART1 :Base clock for UART1 - * - CGU_BASE_UART2 :Base clock for UART2 - * - CGU_BASE_UART3 :Base clock for UART3 - * @return Always return 0 - **********************************************************************/ -uint32_t CGU_GetBaseStatus(CGU_ENTITY_T Base) -{ - switch (Base) { - /*CCU1*/ - case CGU_BASE_APB3: - return LPC_CCU1->BASE_STAT & 1; - - case CGU_BASE_APB1: - return (LPC_CCU1->BASE_STAT >> 1) & 1; - - case CGU_BASE_SPIFI: - return (LPC_CCU1->BASE_STAT >> 2) & 1; - - case CGU_BASE_M4: - return (LPC_CCU1->BASE_STAT >> 3) & 1; - - case CGU_BASE_USB0: - return (LPC_CCU1->BASE_STAT >> 7) & 1; - - case CGU_BASE_USB1: - return (LPC_CCU1->BASE_STAT >> 8) & 1; - - /*CCU2*/ - case CGU_BASE_UART3: - return (LPC_CCU2->BASE_STAT >> 1) & 1; - - case CGU_BASE_UART2: - return (LPC_CCU2->BASE_STAT >> 2) & 1; - - case CGU_BASE_UART1: - return (LPC_CCU2->BASE_STAT >> 3) & 1; - - case CGU_BASE_UART0: - return (LPC_CCU2->BASE_STAT >> 4) & 1; - - case CGU_BASE_SSP1: - return (LPC_CCU2->BASE_STAT >> 5) & 1; - - case CGU_BASE_SSP0: - return (LPC_CCU2->BASE_STAT >> 6) & 1; - - case CGU_BASE_SDIO: - return (LPC_CCU2->BASE_STAT >> 7) & 1; - - /*BASE SAFE is used by WWDT and RGU*/ - case CGU_BASE_SAFE: - break; - - default: - break; - } - - return 0; -} - - -/*********************************************************************//** - * @brief Compare one source clock to IRC clock - * @param[in] Clock Clock entity that will be compared to IRC, should be: - * - CGU_CLKSRC_32KHZ_OSC :32Khz crystal oscillator - * - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock - * - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock - * - CGU_CLKSRC_GP_CLKIN :General purpose input clock - * - CGU_CLKSRC_XTAL_OSC :Crystal oscillator - * - CGU_CLKSRC_PLL0 :PLL0 clock - * - CGU_CLKSRC_PLL1 :PLL1 clock - * - CGU_CLKSRC_IDIVA :Integer divider register A - * - CGU_CLKSRC_IDIVB :Integer divider register B - * - CGU_CLKSRC_IDIVC :Integer divider register C - * - CGU_CLKSRC_IDIVD :Integer divider register D - * - CGU_CLKSRC_IDIVE :Integer divider register E - * - CGU_BASE_SAFE :Base safe clock (always on)for WDT - * - CGU_BASE_USB0 :Base clock for USB0 - * - CGU_BASE_USB1 :Base clock for USB1 - * - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core - * and APB peripheral blocks #0 and #2 - * - CGU_BASE_SPIFI :Base clock for SPIFI - * - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx - * - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx - * - CGU_BASE_APB1 :Base clock for APB peripheral block #1 - * - CGU_BASE_APB3 :Base clock for APB peripheral block #3 - * - CGU_BASE_LCD :Base clock for LCD - * - CGU_BASE_SDIO :Base clock for SDIO card reader - * - CGU_BASE_SSP0 :Base clock for SSP0 - * - CGU_BASE_SSP1 :Base clock for SSP1 - * - CGU_BASE_UART0 :Base clock for UART0 - * - CGU_BASE_UART1 :Base clock for UART1 - * - CGU_BASE_UART2 :Base clock for UART2 - * - CGU_BASE_UART3 :Base clock for UART3 - * - CGU_BASE_CLKOUT :Base clock for CLKOUT pin - * @param[in] m Multiple value pointer - * @param[in] d Divider value pointer - * @return Compare status, could be: - * - (-1): fail - * - 0: successful - * @note Formula used to compare: - * FClock = F_IRC* m / d - **********************************************************************/ -int CGU_FrequencyMonitor(CGU_ENTITY_T Clock, uint32_t *m, uint32_t *d) -{ - uint32_t n, c, temp; - int i; - /* Maximum allow RCOUNT number */ - c = 511; - /* Check Source Clock Freq is larger or smaller */ - LPC_CGU->FREQ_MON = (Clock << 24) | 1 << 23 | c; - - while (LPC_CGU->FREQ_MON & (1 << 23)); - - for (i = 0; i < 10000; i++); - - temp = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF; - - if (temp == 0) { /* too low F < 12000000/511*/ - return -1; - } - - if (temp > 511) { /* larger */ - c = 511 - (LPC_CGU->FREQ_MON & 0x1FF); - - } else { - do { - c--; - LPC_CGU->FREQ_MON = (Clock << 24) | 1 << 23 | c; - - while (LPC_CGU->FREQ_MON & (1 << 23)); - - for (i = 0; i < 10000; i++); - - n = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF; - } while (n == temp); - - c++; - } - - *m = temp; - *d = c; - return 0; -} - -/*********************************************************************//** - * @brief Compare one source clock to another source clock - * @param[in] Clock Clock entity that will be compared to second source, should be: - * - CGU_CLKSRC_32KHZ_OSC :32Khz crystal oscillator - * - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock - * - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock - * - CGU_CLKSRC_GP_CLKIN :General purpose input clock - * - CGU_CLKSRC_XTAL_OSC :Crystal oscillator - * - CGU_CLKSRC_PLL0 :PLL0 clock - * - CGU_CLKSRC_PLL1 :PLL1 clock - * - CGU_CLKSRC_IDIVA :Integer divider register A - * - CGU_CLKSRC_IDIVB :Integer divider register B - * - CGU_CLKSRC_IDIVC :Integer divider register C - * - CGU_CLKSRC_IDIVD :Integer divider register D - * - CGU_CLKSRC_IDIVE :Integer divider register E - * - CGU_BASE_SAFE :Base safe clock (always on)for WDT - * - CGU_BASE_USB0 :Base clock for USB0 - * - CGU_BASE_USB1 :Base clock for USB1 - * - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core - * and APB peripheral blocks #0 and #2 - * - CGU_BASE_SPIFI :Base clock for SPIFI - * - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx - * - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx - * - CGU_BASE_APB1 :Base clock for APB peripheral block #1 - * - CGU_BASE_APB3 :Base clock for APB peripheral block #3 - * - CGU_BASE_LCD :Base clock for LCD - * - CGU_BASE_SDIO :Base clock for SDIO card reader - * - CGU_BASE_SSP0 :Base clock for SSP0 - * - CGU_BASE_SSP1 :Base clock for SSP1 - * - CGU_BASE_UART0 :Base clock for UART0 - * - CGU_BASE_UART1 :Base clock for UART1 - * - CGU_BASE_UART2 :Base clock for UART2 - * - CGU_BASE_UART3 :Base clock for UART3 - * - CGU_BASE_CLKOUT :Base clock for CLKOUT pin - * @param[in] CompareToClock Clock source that to be compared to first source, should be different - * to first source. - * @param[in] m Multiple value pointer - * @param[in] d Divider value pointer - * @return Compare status, could be: - * - (-1): fail - * - 0: successful - * @note Formula used to compare: - * FClock = m*FCompareToClock/d - **********************************************************************/ -uint32_t CGU_RealFrequencyCompare(CGU_ENTITY_T Clock, CGU_ENTITY_T CompareToClock, uint32_t *m, uint32_t *d) -{ - uint32_t m1, m2, d1, d2; - - /* Check Parameter */ - if ((Clock > CGU_CLKSRC_IDIVE) || (CompareToClock > CGU_CLKSRC_IDIVE)) { - return CGU_ERROR_INVALID_PARAM; - } - - /* Check for Clock Enable - Not yet implement - * The Comparator will hang if Clock has not been set*/ - CGU_FrequencyMonitor(Clock, &m1, &d1); - CGU_FrequencyMonitor(CompareToClock, &m2, &d2); - *m = m1 * d2; - *d = d1 * m2; - return 0; -} - diff --git a/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.h b/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.h deleted file mode 100644 index 8857777d7..000000000 --- a/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.h +++ /dev/null @@ -1,265 +0,0 @@ -/** - * @file lpc43xx_cgu.h - * @brief - * - * DAPLink Interface Firmware - * Copyright (c) 2009-2016, ARM Limited, 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 - * - * 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. - */ - -/* Peripheral group ----------------------------------------------------------- */ -/** @defgroup CGU CGU (Clock Generation Unit) - * @ingroup LPC4300CMSIS_FwLib_Drivers - * @{ - */ - -#ifndef lpc43xx_CGU_H_ -#define lpc43xx_CGU_H_ - -/* Includes ------------------------------------------------------------------- */ -#include "LPC43xx.h" -#include "lpc_types.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Private Macros -------------------------------------------------------------- */ -/** @defgroup CGU_Private_Macros CGU Private Macros - * @{ - */ - -/** Branch clocks from CGU_BASE_SAFE */ -#define CGU_ENTITY_NONE CGU_ENTITY_NUM - -/** Check bit at specific position is clear or not */ -#define ISBITCLR(x,bit) ((x&(1<>2 ^ x>>3 ^ x>>4) & 1) << 7 | x>>1 & 0xFF; + return x; + } +} + +#define PLL0_PSEL_MAX (1<<5) +/* post-divider: compute pdec from psel */ +static unsigned pdec_new(unsigned psel) +{ + unsigned x=0x10, ip; + switch (psel) + { + case 0: return 0xFFFFFFFF; + case 1: return 0x62; + case 2: return 0x42; + default: + for (ip = psel; ip <= PLL0_PSEL_MAX; ip++) + x = ((x ^ x>>2) & 1) << 4 | x>>1 & 0x3F; + return x; + } +} + +#define PLL0_MSEL_MAX (1<<15) +/* multiplier: compute mdec from msel */ +static unsigned mdec_new (unsigned msel) +{ + unsigned x=0x4000, im; + switch (msel) + { + case 0: return 0xFFFFFFFF; + case 1: return 0x18003; + case 2: return 0x10003; + default: + for (im = msel; im <= PLL0_MSEL_MAX; im++) + x = (((x ^ (x >> 1)) & 1) << 14) | ((x >> 1) & 0xFFFF); + return x; + } +} + +/* bandwidth: compute seli from msel */ +unsigned anadeci_new(unsigned msel) +{ + unsigned tmp; + if (msel > 16384) return 1; + if (msel > 8192) return 2; + if (msel > 2048) return 4; + if (msel >= 501) return 8; + if (msel >= 60) + { + tmp=1024/(msel+9); + return ( 1024 == ( tmp*(msel+9)) ) == 0 ? tmp*4 : (tmp+1)*4 ; + } + return (msel & 0x3c) + 4; +} + +/* bandwidth: compute selp from msel */ +unsigned anadecp_new(unsigned msel) +{ + if (msel < 60) return (msel>>1) + 1; + return 31; +} + /****************************************************************************** * SetClock ******************************************************************************/ @@ -343,7 +428,7 @@ static void SetClock (void) { (0 << 2) ; /* Low-frequency mode */ /* Wait ~250us @ 12MHz */ - for (i = 1500; i; i--); + WaitUs(250, CLK_XTAL); #ifdef USE_SPIFI /* configure SPIFI clk to IRC via IDIVA (later IDIVA is configured to PLL1/3) */ @@ -380,10 +465,10 @@ static void SetClock (void) { /* CPU base clock is in the mid frequency range before final clock set */ LPC_CGU->BASE_M4_CLK = (0x01 << 11) | /* Autoblock En */ - (0x09 << 24) ; /* Clock source: PLL1 */ + (CLK_SRC_PLL1 << 24) ; /* Clock source: PLL1 */ - /* Max. BASE_M4_CLK frequency here is 102MHz, wait at least 20us */ - for (i = 1050; i; i--); /* Wait minimum 2100 cycles */ + /* Wait 20us */ + WaitUs(20, (CLK_XTAL * (PLL1_MSEL + 1)) / ((PLL1_NSEL + 1) * 2)); #endif /* Configure PLL1 */ LPC_CGU->PLL1_CTRL = (0 << 0) | /* PLL1 Enabled */ @@ -415,63 +500,20 @@ static void SetClock (void) { LPC_CGU->PLL0USB_CTRL |= 1; /* M divider */ - x = 0x00004000; - switch (PLL0USB_M) { - case 0: x = 0xFFFFFFFF; - break; - case 1: x = 0x00018003; - break; - case 2: x = 0x00010003; - break; - default: - for (i = PLL0USB_M; i <= 0x8000; i++) { - x = (((x ^ (x >> 1)) & 1) << 14) | ((x >> 1) & 0x3FFF); - } - } + x = mdec_new(PLL0USB_M); - if (PLL0USB_M < 60) selp = (PLL0USB_M >> 1) + 1; - else selp = 31; - - if (PLL0USB_M > 16384) seli = 1; - else if (PLL0USB_M > 8192) seli = 2; - else if (PLL0USB_M > 2048) seli = 4; - else if (PLL0USB_M >= 501) seli = 8; - else if (PLL0USB_M >= 60) seli = 4 * (1024 / (PLL0USB_M + 9)); - else seli = (PLL0USB_M & 0x3C) + 4; + selp = anadecp_new(PLL0USB_M); + seli = anadeci_new(PLL0USB_M); LPC_CGU->PLL0USB_MDIV = (selp << 17) | (seli << 22) | (x << 0); /* N divider */ - x = 0x80; - switch (PLL0USB_N) { - case 0: x = 0xFFFFFFFF; - break; - case 1: x = 0x00000302; - break; - case 2: x = 0x00000202; - break; - default: - for (i = PLL0USB_N; i <= 0x0100; i++) { - x =(((x ^ (x >> 2) ^ (x >> 3) ^ (x >> 4)) & 1) << 7) | ((x >> 1) & 0x7F); - } - } + x = ndec_new(PLL0USB_N); LPC_CGU->PLL0USB_NP_DIV = (x << 12); /* P divider */ - x = 0x10; - switch (PLL0USB_P) { - case 0: x = 0xFFFFFFFF; - break; - case 1: x = 0x00000062; - break; - case 2: x = 0x00000042; - break; - default: - for (i = PLL0USB_P; i <= 0x200; i++) { - x = (((x ^ (x >> 2)) & 1) << 4) | ((x >> 1) &0x0F); - } - } + x = pdec_new(PLL0USB_P); LPC_CGU->PLL0USB_NP_DIV |= x; LPC_CGU->PLL0USB_CTRL = (PLL0USB_CLK_SEL << 24) | /* Clock source sel */ @@ -481,6 +523,7 @@ static void SetClock (void) { (PLL0USB_DIRECTI << 2 ) | /* Direct input */ (PLL0USB_BYPASS << 1 ) | /* PLL bypass */ (0 << 0 ) ; /* PLL0USB Enabled */ + LPC_CREG->CREG0 &= ~(1 << 5); // Enable USB0 PHY power. while (!(LPC_CGU->PLL0USB_STAT & 1)); @@ -516,17 +559,6 @@ static void SetClock (void) { } -/*---------------------------------------------------------------------------- - Approximate delay function (must be used after SystemCoreClockUpdate() call) - *----------------------------------------------------------------------------*/ -#define CPU_NANOSEC(x) (((uint64_t)(x) * SystemCoreClock)/1000000000) - -static void WaitUs (uint32_t us) { - uint32_t cyc = us * CPU_NANOSEC(1000)/4; - while(cyc--); -} - - /*---------------------------------------------------------------------------- Measure frequency using frequency monitor *----------------------------------------------------------------------------*/ @@ -545,7 +577,7 @@ uint32_t MeasureFreq (uint32_t clk_sel) { } } fcnt = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF; - fout = fcnt * (12000000U/511U); /* FCNT * (IRC_CLK / RCNT) */ + fout = fcnt * (CLK_IRC/511U); /* FCNT * (IRC_CLK / RCNT) */ return (fout); } diff --git a/source/hic_hal/nxp/lpc4322/uart.c b/source/hic_hal/nxp/lpc4322/uart.c index 5bf10a9e9..6383265e0 100644 --- a/source/hic_hal/nxp/lpc4322/uart.c +++ b/source/hic_hal/nxp/lpc4322/uart.c @@ -3,7 +3,7 @@ * @brief * * DAPLink Interface Firmware - * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved + * Copyright (c) 2020 Arm Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -19,241 +19,167 @@ * limitations under the License. */ +#include "string.h" #include "LPC43xx.h" +#include "RTE_Driver/USART_LPC43xx.h" #include "uart.h" -#include "lpc43xx_cgu.h" -#include "lpc43xx_scu.h" #include "util.h" +#include "cortex_m.h" #include "circ_buf.h" #include "settings.h" // for config_get_overflow_detect -static uint32_t baudrate; -static uint32_t dll; -static uint32_t tx_in_progress; +#define USART_INSTANCE (Driver_USART0) +#define USART_IRQ (USART0_IRQn) extern uint32_t SystemCoreClock; +static void clear_buffers(void); + #define RX_OVRF_MSG "\n" #define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1) -#define BUFFER_SIZE (512) +#define BUFFER_SIZE (512) circ_buf_t write_buffer; uint8_t write_buffer_data[BUFFER_SIZE]; circ_buf_t read_buffer; uint8_t read_buffer_data[BUFFER_SIZE]; -static int32_t reset(void); +struct { + // Number of bytes pending to be transferred. This is 0 if there is no + // ongoing transfer and the uart_handler processed the last transfer. + volatile uint32_t tx_size; -#define UART_IRQn USART0_IRQn -#define LPC_USART LPC_USART0 -#define UART_IRQHandler USART0_IRQHandler + uint8_t rx; +} cb_buf; -// UART Control Pin P2_2: GPIO5[2] -#define PORT_UARTCTRL 5 -#define PIN_UARTCTRL_IN_BIT 2 -#define PIN_UARTCTRL (1<CLR[PORT_UARTCTRL] = PIN_UARTCTRL; - LPC_GPIO_PORT->DIR[PORT_UARTCTRL] |= (PIN_UARTCTRL); - // enable FIFOs (trigger level 1) and clear them - LPC_USART->FCR = 0x87; - // Transmit Enable - LPC_USART->TER = 0x01; - // reset uart - reset(); - // enable rx and tx interrupt - LPC_USART->IER |= (1 << 0) | (1 << 1); - NVIC_EnableIRQ(UART_IRQn); + clear_buffers(); + cb_buf.tx_size = 0; + USART_INSTANCE.Initialize(uart_handler); + USART_INSTANCE.PowerControl(ARM_POWER_FULL); + return 1; } int32_t uart_uninitialize(void) { - // disable interrupt - LPC_USART->IER &= ~(0x7); - NVIC_DisableIRQ(UART_IRQn); - // reset uart - reset(); + USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0); + USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); + USART_INSTANCE.PowerControl(ARM_POWER_OFF); + USART_INSTANCE.Uninitialize(); + clear_buffers(); + cb_buf.tx_size = 0; + return 1; } int32_t uart_reset(void) { // disable interrupt - NVIC_DisableIRQ(UART_IRQn); - // reset uart - reset(); + NVIC_DisableIRQ(USART_IRQ); + clear_buffers(); // enable interrupt - NVIC_EnableIRQ(UART_IRQn); + NVIC_EnableIRQ(USART_IRQ); + return 1; } int32_t uart_set_configuration(UART_Configuration *config) { - uint8_t DivAddVal = 0; - uint8_t MulVal = 1; - uint8_t mv, data_bits = 8, parity, stop_bits = 0; - // disable interrupt - NVIC_DisableIRQ(UART_IRQn); - // reset uart - reset(); - baudrate = config->Baudrate; - // Compute baud rate dividers - mv = 15; - dll = util_div_round_down(SystemCoreClock, 16 * config->Baudrate); - DivAddVal = util_div_round(SystemCoreClock * mv, dll * config->Baudrate * 16) - mv; - // set LCR[DLAB] to enable writing to divider registers - LPC_USART->LCR |= (1 << 7); - // set divider values - LPC_USART->DLM = (dll >> 8) & 0xFF; - LPC_USART->DLL = (dll >> 0) & 0xFF; - LPC_USART->FDR = (uint32_t) DivAddVal << 0 - | (uint32_t) MulVal << 4; - // clear LCR[DLAB] - LPC_USART->LCR &= ~(1 << 7); - - // set data bits, stop bits, parity - if ((config->DataBits < 5) || (config->DataBits > 8)) { - data_bits = 8; - } - - data_bits -= 5; - - if (config->StopBits != 1 && config->StopBits != 2) { - stop_bits = 1; - } - - stop_bits -= 1; - - switch (config->Parity) { - case UART_PARITY_ODD: - parity = 0x01; - break; // Parity Odd - - case UART_PARITY_EVEN: - parity = 0x03; - break; // Parity Even + uint32_t control = ARM_USART_MODE_ASYNCHRONOUS; - case UART_PARITY_MARK: - parity = 0x05; - break; // Parity Mark - - case UART_PARITY_SPACE: - parity = 0x07; - break; // Parity Space - - case UART_PARITY_NONE: // Parity None - default: - parity = 0x00; + switch (config->DataBits) { + case UART_DATA_BITS_5: + control |= ARM_USART_DATA_BITS_5; break; - } - - LPC_USART->LCR = (data_bits << 0) - | (stop_bits << 2) - | (parity << 3); - // Enable UART interrupt - NVIC_EnableIRQ(UART_IRQn); - return 1; -} -int32_t uart_get_configuration(UART_Configuration *config) -{ - float br; - uint32_t lcr; - // line control parameter - lcr = LPC_USART->LCR; - // baudrate - br = SystemCoreClock / (dll * 16); - - // If inside +/- 2% tolerance - if (((br * 100) <= (baudrate * 102)) && ((br * 100) >= (baudrate * 98))) { - config->Baudrate = baudrate; - } else { - config->Baudrate = br; - } + case UART_DATA_BITS_6: + control |= ARM_USART_DATA_BITS_6; + break; - // get data bits - switch ((lcr >> 0) & 3) { - case 0: - config->DataBits = UART_DATA_BITS_5; + case UART_DATA_BITS_7: + control |= ARM_USART_DATA_BITS_7; break; - case 1: - config->DataBits = UART_DATA_BITS_6; + case UART_DATA_BITS_8: /* fallthrough */ + default: + control |= ARM_USART_DATA_BITS_8; break; + } - case 2: - config->DataBits = UART_DATA_BITS_7; + switch (config->Parity) { + case UART_PARITY_EVEN: + control |= ARM_USART_PARITY_EVEN; break; - case 3: - config->DataBits = UART_DATA_BITS_8; + case UART_PARITY_ODD: + control |= ARM_USART_PARITY_ODD; break; + case UART_PARITY_NONE: /* fallthrough */ default: - return 0; + control |= ARM_USART_PARITY_NONE; + break; } - // get parity - switch ((lcr >> 3) & 7) { - case 0: - case 2: - case 4: - case 6: - config->Parity = UART_PARITY_NONE; + switch (config->StopBits) { + case UART_STOP_BITS_1: /* fallthrough */ + default: + control |= ARM_USART_STOP_BITS_1; break; - case 1: - config->Parity = UART_PARITY_ODD; + case UART_STOP_BITS_1_5: + control |= ARM_USART_STOP_BITS_1_5; break; - case 3: - config->Parity = UART_PARITY_MARK; + case UART_STOP_BITS_2: + control |= ARM_USART_STOP_BITS_2; break; + } - case 5: - config->Parity = UART_PARITY_EVEN; + switch (config->FlowControl) { + case UART_FLOW_CONTROL_NONE: /* fallthrough */ + default: + control |= ARM_USART_FLOW_CONTROL_NONE; break; - case 7: - config->Parity = UART_PARITY_SPACE; + case UART_FLOW_CONTROL_RTS_CTS: + control |= ARM_USART_FLOW_CONTROL_RTS_CTS; break; - - default: - return 0; } - // get stop bits - switch ((lcr >> 2) & 1) { - case 0: - config->StopBits = UART_STOP_BITS_1; - break; + NVIC_DisableIRQ(USART_IRQ); + clear_buffers(); - case 1: - config->StopBits = UART_STOP_BITS_2; - break; + // If there was no Receive() call in progress aborting it is harmless. + USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0U); + USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U); - default: - return 0; + uint32_t r = USART_INSTANCE.Control(control, config->Baudrate); + if (r != ARM_DRIVER_OK) { + return 0; } + USART_INSTANCE.Control(ARM_USART_CONTROL_TX, 1); + USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 1); + USART_INSTANCE.Receive(&(cb_buf.rx), 1); + + NVIC_ClearPendingIRQ(USART_IRQ); + NVIC_EnableIRQ(USART_IRQ); + + return 1; +} - // get flow control - config->FlowControl = UART_FLOW_CONTROL_NONE; +int32_t uart_get_configuration(UART_Configuration *config) +{ return 1; } @@ -266,104 +192,65 @@ int32_t uart_write_free(void) return circ_buf_count_free(&write_buffer); } +// Start a new TX transfer if there are bytes pending to be transferred on the +// write_buffer buffer. The transferred bytes are not removed from the circular +// by this function, only the event handler will remove them once the transfer +// is done. +static void uart_start_tx_transfer() { + uint32_t tx_size = 0; + const uint8_t* buf = circ_buf_peek(&write_buffer, &tx_size); + if (tx_size > BUFFER_SIZE / 4) { + // The bytes being transferred remain on the circular buffer memory + // until the transfer is done. Limiting the UART transfer size + // allows the uart_handler to clear those bytes earlier. + tx_size = BUFFER_SIZE / 4; + } + cb_buf.tx_size = tx_size; + if (tx_size) { + USART_INSTANCE.Send(buf, tx_size); + } +} + int32_t uart_write_data(uint8_t *data, uint16_t size) { - uint32_t cnt; - - cnt = circ_buf_write(&write_buffer, data, size); - - // Make sure that the target LPC1549 can receive the output - LPC_GPIO_PORT->SET[PORT_UARTCTRL] = PIN_UARTCTRL; - - // enable THRE interrupt - LPC_USART->IER |= (1 << 1); + if (size == 0) { + return 0; + } - if (!tx_in_progress) { - // force THRE interrupt to start - NVIC_SetPendingIRQ(UART_IRQn); + uint32_t cnt = circ_buf_write(&write_buffer, data, size); + if (cb_buf.tx_size == 0) { + // There's no pending transfer and the value of cb_buf.tx_size will not + // change to non-zero by the event handler once it is zero. Note that it + // is entirely possible that we transferred all the bytes we added to + // the circular buffer in this function by the time we are in this + // branch, in that case uart_start_tx_transfer() would not schedule any + // transfer. + uart_start_tx_transfer(); } return cnt; } - int32_t uart_read_data(uint8_t *data, uint16_t size) { return circ_buf_read(&read_buffer, data, size); } -void uart_enable_flow_control(bool enabled) -{ - // Flow control not implemented for this platform -} - -void UART_IRQHandler(void) -{ - uint32_t iir; - // read interrupt status - iir = LPC_USART->IIR; - - // handle character to transmit - if (circ_buf_count_used(&write_buffer) > 0) { - // if THR is empty - if (LPC_USART->LSR & (1 << 5)) { - LPC_USART->THR = circ_buf_pop(&write_buffer); - tx_in_progress = 1; +void uart_handler(uint32_t event) { + if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) { + uint32_t free = circ_buf_count_free(&read_buffer); + if (free > RX_OVRF_MSG_SIZE) { + circ_buf_push(&read_buffer, cb_buf.rx); + } else if ((RX_OVRF_MSG_SIZE == free) && config_get_overflow_detect()) { + circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); + } else { + // Drop character } - - } else if (tx_in_progress) { - tx_in_progress = 0; - // Turn back input for the target LPC1549 to it's pinlist - LPC_GPIO_PORT->CLR[PORT_UARTCTRL] = PIN_UARTCTRL; - // disable THRE interrupt - LPC_USART->IER &= ~(1 << 1); + USART_INSTANCE.Receive(&(cb_buf.rx), 1); } - // handle received character - if (((iir & 0x0E) == 0x04) || // Rx interrupt (RDA) - ((iir & 0x0E) == 0x0C)) { // Rx interrupt (CTI) - while (LPC_USART->LSR & 0x01) { - uint32_t free; - uint8_t data; - - data = LPC_USART->RBR; - free = circ_buf_count_free(&read_buffer); - if (free > RX_OVRF_MSG_SIZE) { - circ_buf_push(&read_buffer, data); - } else if (config_get_overflow_detect()) { - if (RX_OVRF_MSG_SIZE == free) { - circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); - } else { - // Drop newest - } - } else { - // Drop oldest - circ_buf_pop(&read_buffer); - circ_buf_push(&read_buffer, data); - } - } + if (event & ARM_USART_EVENT_SEND_COMPLETE) { + circ_buf_pop_n(&write_buffer, cb_buf.tx_size); + uart_start_tx_transfer(); } - - LPC_USART->LSR; -} - -static int32_t reset(void) -{ - // Reset FIFOs - LPC_USART->FCR = 0x06; - baudrate = 0; - dll = 0; - tx_in_progress = 0; - - circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data)); - circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data)); - - // Ensure a clean start, no data in either TX or RX FIFO - while ((LPC_USART->LSR & ((1 << 5) | (1 << 6))) != ((1 << 5) | (1 << 6))); - - while (LPC_USART->LSR & 0x01) { - LPC_USART->RBR; // Dump data from RX FIFO - } - - return 1; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy