From 887c9fb4b1344324d9156db9f17e5ed01f867b2b Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 20:51:28 +0200 Subject: [PATCH 01/12] lpc43xx_hic: remove lpc43xx_cgu.{c|h} --- source/hic_hal/nxp/lpc4322/lpc43xx_cgu.c | 1132 ---------------------- source/hic_hal/nxp/lpc4322/lpc43xx_cgu.h | 265 ----- 2 files changed, 1397 deletions(-) delete mode 100644 source/hic_hal/nxp/lpc4322/lpc43xx_cgu.c delete mode 100644 source/hic_hal/nxp/lpc4322/lpc43xx_cgu.h 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< Date: Sun, 9 Jan 2022 20:55:43 +0200 Subject: [PATCH 02/12] lpc43xx_hic,uart: replace CGU code with direct register setup --- source/hic_hal/nxp/lpc4322/uart.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/uart.c b/source/hic_hal/nxp/lpc4322/uart.c index 5bf10a9e9..b69c12e04 100644 --- a/source/hic_hal/nxp/lpc4322/uart.c +++ b/source/hic_hal/nxp/lpc4322/uart.c @@ -21,7 +21,6 @@ #include "LPC43xx.h" #include "uart.h" -#include "lpc43xx_cgu.h" #include "lpc43xx_scu.h" #include "util.h" #include "circ_buf.h" @@ -31,8 +30,6 @@ static uint32_t baudrate; static uint32_t dll; static uint32_t tx_in_progress; -extern uint32_t SystemCoreClock; - #define RX_OVRF_MSG "\n" #define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1) #define BUFFER_SIZE (512) @@ -56,11 +53,18 @@ static int32_t reset(void); int32_t uart_initialize(void) { + uint32_t tmp; NVIC_DisableIRQ(UART_IRQn); // The baudrate calculations require the UART to be clocked as SystemCoreClock - CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_UART0); - CGU_EnableEntity(CGU_BASE_UART0, ENABLE); + tmp = LPC_CGU->BASE_UART0_CLK & ~(0x0F << 24); // clear CLK_SEL. + LPC_CGU->BASE_UART0_CLK = tmp + | (0x01 << 11) // AUTOBLOCK: 0=Disabled, 1=Enabled. + | (0x09 << 24) // CLK_SEL = PLL1. + ; + + LPC_CGU->BASE_UART0_CLK &= ~1; // PD: 0=Power Up. + scu_pinmux(2, 0, UART_RX_TX, FUNC1); /* P2_0: U0_TXD */ scu_pinmux(2, 1, UART_RX_TX, FUNC1); /* P2_1: U0_RXD */ From f1315ba65368ce1bf76eecd70a0c865ce5b0d1a7 Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 20:58:04 +0200 Subject: [PATCH 03/12] lpc43xx_hic,system: extract N setup as ndec_new --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 30 ++++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index 8b0e13fab..bca60ef46 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -319,6 +319,22 @@ uint32_t GetClockFreq (uint32_t clk_src); uint32_t SystemCoreClock = 120000000U; /* System Clock Frequency (Core Clock) */ +#define PLL0_NSEL_MAX (1<<8) +/* pre-divider: compute ndec from nsel */ +static unsigned ndec_new(unsigned nsel) +{ + unsigned x=0x80, in; + switch (nsel) + { + case 0: return 0xFFFFFFFF; + case 1: return 0x302; + case 2: return 0x202; + default: + for (in = nsel; in <= PLL0_NSEL_MAX; in++) + x = ((x ^ x>>2 ^ x>>3 ^ x>>4) & 1) << 7 | x>>1 & 0xFF; + return x; + } +} /****************************************************************************** * SetClock ******************************************************************************/ @@ -443,19 +459,7 @@ static void SetClock (void) { (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 */ From ca753ed399e633f115875dc11ae6a79e80f826ee Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 20:59:03 +0200 Subject: [PATCH 04/12] lpc43xx_hic,system: extract P setup as pdec_new --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 31 ++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index bca60ef46..5c77d6fbd 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -335,6 +335,23 @@ static unsigned ndec_new(unsigned nsel) 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; + } +} /****************************************************************************** * SetClock ******************************************************************************/ @@ -463,19 +480,7 @@ static void SetClock (void) { 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 */ From abcbeec42bf344877594c6d2225e05696166b683 Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 20:59:53 +0200 Subject: [PATCH 05/12] lpc43xx_hic,system: extract M setup as mdec_new --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 31 ++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index 5c77d6fbd..b1504cd43 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -352,6 +352,23 @@ static unsigned pdec_new(unsigned psel) 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; + } +} /****************************************************************************** * SetClock ******************************************************************************/ @@ -448,19 +465,7 @@ 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; From dd0bb84154e056b2c17dd879bae0e7e84f2ac6c6 Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 21:01:07 +0200 Subject: [PATCH 06/12] lpc43xx_hic,system: extract SELI setup as anadeci_new --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 24 +++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index b1504cd43..2a8b2099c 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -369,6 +369,22 @@ static unsigned mdec_new (unsigned msel) 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; +} /****************************************************************************** * SetClock ******************************************************************************/ @@ -469,13 +485,7 @@ static void SetClock (void) { 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; + seli = anadeci_new(PLL0USB_M); LPC_CGU->PLL0USB_MDIV = (selp << 17) | (seli << 22) | (x << 0); From cd0f4ae12ab665f2bb932d9fd60454a732e20e63 Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 21:01:40 +0200 Subject: [PATCH 07/12] lpc43xx_hic,system: extract SELI setup as anadecp_new --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index 2a8b2099c..ddf649e85 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -385,6 +385,14 @@ unsigned anadeci_new(unsigned msel) } return (msel & 0x3c) + 4; } + +/* bandwidth: compute selp from msel */ +unsigned anadecp_new(unsigned msel) +{ + if (msel < 60) return (msel>>1) + 1; + return 31; +} + /****************************************************************************** * SetClock ******************************************************************************/ @@ -483,8 +491,7 @@ static void SetClock (void) { /* M divider */ x = mdec_new(PLL0USB_M); - if (PLL0USB_M < 60) selp = (PLL0USB_M >> 1) + 1; - else selp = 31; + selp = anadecp_new(PLL0USB_M); seli = anadeci_new(PLL0USB_M); LPC_CGU->PLL0USB_MDIV = (selp << 17) | (seli << 22) | From 0885a2ddbf959fe01926276e60f0bb118a9c0480 Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 21:02:56 +0200 Subject: [PATCH 08/12] lpc43xx_hic,system: make use of WaitUs --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index ddf649e85..55b97c307 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -319,6 +319,17 @@ uint32_t GetClockFreq (uint32_t clk_src); uint32_t SystemCoreClock = 120000000U; /* System Clock Frequency (Core Clock) */ +/*---------------------------------------------------------------------------- + Approximate delay function (must be used after SystemCoreClockUpdate() call) + *----------------------------------------------------------------------------*/ +static void WaitUs(uint32_t us, uint32_t clock_hz) +{ + us *= (clock_hz / 1000000) / 3; + + while (us--); +} + + #define PLL0_NSEL_MAX (1<<8) /* pre-divider: compute ndec from nsel */ static unsigned ndec_new(unsigned nsel) @@ -417,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) */ @@ -456,8 +467,8 @@ static void SetClock (void) { LPC_CGU->BASE_M4_CLK = (0x01 << 11) | /* Autoblock En */ (0x09 << 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 */ @@ -547,17 +558,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 *----------------------------------------------------------------------------*/ From a3e0b089078a31b8972fbceb0112b8123d794e0b Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 21:04:02 +0200 Subject: [PATCH 09/12] lpc43xx_hic,system: use defines where possible --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index 55b97c307..bf6e6e902 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -465,7 +465,7 @@ 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 */ /* Wait 20us */ WaitUs(20, (CLK_XTAL * (PLL1_MSEL + 1)) / ((PLL1_NSEL + 1) * 2)); @@ -576,7 +576,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); } From 3026c65de1375231613442d63da4cee14ea4421b Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 21:04:36 +0200 Subject: [PATCH 10/12] lpc43xx_hic,system: Enable USB0 PHY power this part is taken from board_LPC43xx.c --- source/hic_hal/nxp/lpc4322/system_LPC43xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c index bf6e6e902..39f4f21cb 100644 --- a/source/hic_hal/nxp/lpc4322/system_LPC43xx.c +++ b/source/hic_hal/nxp/lpc4322/system_LPC43xx.c @@ -523,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)); From 88d4bda1cad1e10551c1b224c93c01392a53dd2f Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Sun, 9 Jan 2022 21:05:43 +0200 Subject: [PATCH 11/12] lpc43xx_hic,board: remove CGU code --- source/hic_hal/nxp/lpc4322/board_LPC43xx.c | 17 ----------------- 1 file changed, 17 deletions(-) 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); } From 422c5cc10a68caa58efb6e244b8d6fb4632f28bc Mon Sep 17 00:00:00 2001 From: Adrian Negreanu Date: Tue, 15 Feb 2022 18:20:29 +0200 Subject: [PATCH 12/12] lp43xx: use Driver_USART0 for virtual com port The code is adapted from lpc55xx/uart.c. --- source/hic_hal/nxp/lpc4322/RTE_Device.h | 6 +- source/hic_hal/nxp/lpc4322/uart.c | 393 +++++++++--------------- 2 files changed, 141 insertions(+), 258 deletions(-) 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/uart.c b/source/hic_hal/nxp/lpc4322/uart.c index b69c12e04..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,245 +19,167 @@ * limitations under the License. */ +#include "string.h" #include "LPC43xx.h" +#include "RTE_Driver/USART_LPC43xx.h" #include "uart.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<BASE_UART0_CLK & ~(0x0F << 24); // clear CLK_SEL. - LPC_CGU->BASE_UART0_CLK = tmp - | (0x01 << 11) // AUTOBLOCK: 0=Disabled, 1=Enabled. - | (0x09 << 24) // CLK_SEL = PLL1. - ; - - LPC_CGU->BASE_UART0_CLK &= ~1; // PD: 0=Power Up. - - scu_pinmux(2, 0, UART_RX_TX, FUNC1); /* P2_0: U0_TXD */ - scu_pinmux(2, 1, UART_RX_TX, FUNC1); /* P2_1: U0_RXD */ - - scu_pinmux(2, 2, GPIO_NOPULL, FUNC4); /* UARTCTRL: GPIO5[2] */ - // Control target's UART RX: - // UARTCTRL high: The LPC1549 gets uart input from the LPC4322 - // UARTCTRL low: The LPC1549 gets uart input from the ISP_RX on the pinlist - LPC_GPIO_PORT->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 - - case UART_PARITY_MARK: - parity = 0x05; - break; // Parity Mark - - case UART_PARITY_SPACE: - parity = 0x07; - break; // Parity Space + uint32_t control = ARM_USART_MODE_ASYNCHRONOUS; - 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; } @@ -270,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; }