Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers system_max32625.c Source File

system_max32625.c

00001 /*******************************************************************************
00002  * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020  * OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * Except as contained in this notice, the name of Maxim Integrated
00023  * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024  * Products, Inc. Branding Policy.
00025  *
00026  * The mere transfer of this software does not imply any licenses
00027  * of trade secrets, proprietary technology, copyrights, patents,
00028  * trademarks, maskwork rights, or any other form of intellectual
00029  * property whatsoever. Maxim Integrated Products, Inc. retains all
00030  * ownership rights.
00031  *
00032  ******************************************************************************/
00033 
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include "max32625.h"
00038 #include "clkman_regs.h"
00039 #include "adc_regs.h"
00040 #include "pwrseq_regs.h"
00041 #include "pwrman_regs.h"
00042 #include "icc_regs.h"
00043 #include "flc_regs.h"
00044 #include "rtc_regs.h"
00045 #include "trim_regs.h"
00046 
00047 #ifndef RO_FREQ
00048 #define RO_FREQ     96000000
00049 #endif
00050 
00051 #ifndef LP0_POST_HOOK
00052 #define LP0_POST_HOOK
00053 #endif
00054 
00055 /*
00056 * Note: When compiling on ARM Keil Toolchain only.
00057 * If the SystemCoreClock is left uninitialized, post Scatter load
00058 * the clock will default to system reset value(48MHz)
00059 */
00060 uint32_t SystemCoreClock = RO_FREQ;
00061 
00062 void SystemCoreClockUpdate(void)
00063 {
00064     if (MXC_PWRSEQ->reg0 & MXC_F_PWRSEQ_REG0_PWR_RCEN_RUN) {
00065         /* 4 MHz source */
00066         if (MXC_PWRSEQ->reg3 & MXC_F_PWRSEQ_REG3_PWR_RC_DIV) {
00067             SystemCoreClock = (4000000 / (0x1 << ((MXC_PWRSEQ->reg3 & MXC_F_PWRSEQ_REG3_PWR_RC_DIV) >>
00068                 MXC_F_PWRSEQ_REG3_PWR_RC_DIV_POS)));
00069         } else {
00070             SystemCoreClock = 4000000;
00071         }
00072     } else {
00073         /* 96 MHz source */
00074         if (MXC_PWRSEQ->reg3 & MXC_F_PWRSEQ_REG3_PWR_RO_DIV) {
00075             SystemCoreClock = (RO_FREQ / (0x1 << ((MXC_PWRSEQ->reg3 & MXC_F_PWRSEQ_REG3_PWR_RO_DIV) >>
00076                 MXC_F_PWRSEQ_REG3_PWR_RO_DIV_POS)));
00077         } else {
00078             SystemCoreClock = RO_FREQ;
00079         }
00080     }
00081 }
00082 
00083 void CLKMAN_TrimRO(void)
00084 {
00085     uint32_t running;
00086     uint32_t trim;
00087 
00088     /* Step 1: enable 32KHz RTC */
00089     running = MXC_PWRSEQ->reg0 & MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
00090     MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
00091 
00092     /* Wait for RTC warm-up */
00093     while(MXC_RTCCFG->osc_ctrl & MXC_F_RTC_OSC_CTRL_OSC_WARMUP_ENABLE) {}
00094 
00095     /* Step 2: enable RO calibration complete interrupt */
00096     MXC_ADC->intr |= MXC_F_ADC_INTR_RO_CAL_DONE_IE;
00097 
00098     /* Step 3: clear RO calibration complete interrupt */
00099     MXC_ADC->intr |= MXC_F_ADC_INTR_RO_CAL_DONE_IF;
00100 
00101     /* Step 4: -- NO LONGER NEEDED / HANDLED BY STARTUP CODE -- */
00102 
00103     /* Step 5: write initial trim to frequency calibration initial condition register */
00104     trim = (MXC_PWRSEQ->reg6 & MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF) >> MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF_POS;
00105     MXC_ADC->ro_cal1 = (MXC_ADC->ro_cal1 & ~MXC_F_ADC_RO_CAL1_TRM_INIT) |
00106                        ((trim << MXC_F_ADC_RO_CAL1_TRM_INIT_POS) & MXC_F_ADC_RO_CAL1_TRM_INIT);
00107 
00108     /* Step 6: load initial trim to active frequency trim register */
00109     MXC_ADC->ro_cal0 |= MXC_F_ADC_RO_CAL0_RO_CAL_LOAD;
00110 
00111     /* Step 7: enable frequency loop to control RO trim */
00112     MXC_ADC->ro_cal0 |= MXC_F_ADC_RO_CAL0_RO_CAL_EN;
00113 
00114     /* Step 8: run frequency calibration in atomic mode */
00115     MXC_ADC->ro_cal0 |= MXC_F_ADC_RO_CAL0_RO_CAL_ATOMIC;
00116 
00117     /* Step 9: waiting for ro_cal_done flag */
00118     while(!(MXC_ADC->intr & MXC_F_ADC_INTR_RO_CAL_DONE_IF));
00119 
00120     /* Step 10: stop frequency calibration */
00121     MXC_ADC->ro_cal0 &= ~MXC_F_ADC_RO_CAL0_RO_CAL_RUN;
00122 
00123     /* Step 11: disable RO calibration complete interrupt */
00124     MXC_ADC->intr &= ~MXC_F_ADC_INTR_RO_CAL_DONE_IE;
00125 
00126     /* Step 12: read final frequency trim value */
00127     trim = (MXC_ADC->ro_cal0 & MXC_F_ADC_RO_CAL0_RO_TRM) >> MXC_F_ADC_RO_CAL0_RO_TRM_POS;
00128 
00129     /* Step 13: write final trim to RO flash trim shadow register */
00130     MXC_PWRSEQ->reg6 = (MXC_PWRSEQ->reg6 & ~MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF) |
00131                        ((trim << MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF_POS) & MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF);
00132 
00133     /* Step 14: restore RTC status */
00134     if (!running) {
00135         MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
00136     }
00137 
00138     /* Step 15: disable frequency loop to control RO trim */
00139     MXC_ADC->ro_cal0 &= ~MXC_F_ADC_RO_CAL0_RO_CAL_EN;
00140 }
00141 
00142 static void ICC_Enable(void)
00143 {
00144     /* Invalidate cache and wait until ready */
00145     MXC_ICC->invdt_all = 1;
00146     while (!(MXC_ICC->ctrl_stat & MXC_F_ICC_CTRL_STAT_READY));
00147 
00148     /* Enable cache */
00149     MXC_ICC->ctrl_stat |= MXC_F_ICC_CTRL_STAT_ENABLE;
00150 
00151     /* Must invalidate a second time for proper use */
00152     MXC_ICC->invdt_all = 1;
00153 }
00154 
00155 /* This function is called before C runtime initialization and can be
00156  * implemented by the application for early initializations. If a value other
00157  * than '0' is returned, the C runtime initialization will be skipped.
00158  *
00159  * You may over-ride this function in your program by defining a custom
00160  *  PreInit(), but care should be taken to reproduce the initilization steps
00161  *  or a non-functional system may result.
00162  */
00163 __weak int PreInit(void)
00164 {
00165     /* Increase system clock to 96 MHz */
00166     MXC_CLKMAN->clk_ctrl = MXC_V_CLKMAN_CLK_CTRL_SYSTEM_SOURCE_SELECT_96MHZ_RO;
00167 
00168     /* Performance-measurement hook, may be defined as nothing */
00169     LP0_POST_HOOK;
00170 
00171     /* Enable cache here to reduce boot time */
00172     ICC_Enable();
00173 
00174     return 0;
00175 }
00176 
00177 /*
00178 * Note: When compiling on ARM Keil Toolchain only.
00179 * If any global variable is modified in this function, post Scatter load
00180 * it will default to its original value(E.g.: SystemCoreClock)
00181 */
00182 /* This function can be implemented by the application to initialize the board */
00183 __weak int Board_Init(void)
00184 {
00185     /* Do nothing */
00186     return 0;
00187 }
00188 
00189 /* This function is called just before control is transferred to main().
00190  *
00191  * You may over-ride this function in your program by defining a custom
00192  *  SystemInit(), but care should be taken to reproduce the initialization
00193  *  steps or a non-functional system may result.
00194  */
00195 __weak void SystemInit(void)
00196 {
00197     /* Copy trim information from shadow registers into power manager registers */
00198     /* NOTE: Checks have been added to prevent bad/missing trim values from being loaded */
00199     if ((MXC_FLC->ctrl & MXC_F_FLC_CTRL_INFO_BLOCK_VALID) &&
00200             (MXC_TRIM->for_pwr_reg5 != 0xffffffff) &&
00201             (MXC_TRIM->for_pwr_reg6 != 0xffffffff)) {
00202         MXC_PWRSEQ->reg5 = MXC_TRIM->for_pwr_reg5;
00203         MXC_PWRSEQ->reg6 = MXC_TRIM->for_pwr_reg6;
00204     } else {
00205         /* No valid info block, use some reasonable defaults */
00206         MXC_PWRSEQ->reg6 &= ~MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF;
00207         MXC_PWRSEQ->reg6 |= (0x1e0 << MXC_F_PWRSEQ_REG6_PWR_TRIM_OSC_VREF_POS);
00208     }
00209 
00210     /* Improve flash access timing */
00211     MXC_FLC->perform |= (MXC_F_FLC_PERFORM_EN_BACK2BACK_RDS |
00212                          MXC_F_FLC_PERFORM_EN_MERGE_GRAB_GNT |
00213                          MXC_F_FLC_PERFORM_AUTO_TACC |
00214                          MXC_F_FLC_PERFORM_AUTO_CLKDIV);
00215 
00216     /* First, eliminate the unnecessary RTC handshake between clock domains. Must be set as a pair. */
00217     MXC_RTCTMR->ctrl |= (MXC_F_RTC_CTRL_USE_ASYNC_FLAGS |
00218                          MXC_F_RTC_CTRL_AGGRESSIVE_RST);
00219     /* Enable fast read of the RTC timer value, and fast write of all other RTC registers */
00220     MXC_PWRSEQ->rtc_ctrl2 |= (MXC_F_PWRSEQ_RTC_CTRL2_TIMER_AUTO_UPDATE |
00221                               MXC_F_PWRSEQ_RTC_CTRL2_TIMER_ASYNC_WR);
00222 
00223     MXC_PWRSEQ->rtc_ctrl2 &= ~(MXC_F_PWRSEQ_RTC_CTRL2_TIMER_ASYNC_RD);
00224 
00225     /* Clear the GPIO WUD event if not waking up from LP0 */
00226     /* this is necessary because WUD flops come up in undetermined state out of POR or SRST*/
00227     if(MXC_PWRSEQ->reg0 & MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT ||
00228        !(MXC_PWRMAN->pwr_rst_ctrl & MXC_F_PWRMAN_PWR_RST_CTRL_POR)) {
00229         /* Clear GPIO WUD event and configuration registers, globally */
00230         MXC_PWRSEQ->reg1 |= (MXC_F_PWRSEQ_REG1_PWR_CLR_IO_EVENT_LATCH |
00231                              MXC_F_PWRSEQ_REG1_PWR_CLR_IO_CFG_LATCH);
00232         MXC_PWRSEQ->reg1 &= ~(MXC_F_PWRSEQ_REG1_PWR_CLR_IO_EVENT_LATCH |
00233                               MXC_F_PWRSEQ_REG1_PWR_CLR_IO_CFG_LATCH);
00234     } else {
00235         /* Unfreeze the GPIO by clearing MBUS_GATE, when returning from LP0 */
00236         MXC_PWRSEQ->reg1 &= ~(MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE);
00237         /* LP0 wake-up: Turn off special switch to eliminate ~50nA of leakage on VDD12 */
00238         MXC_PWRSEQ->reg1 &= ~MXC_F_PWRSEQ_REG1_PWR_SRAM_NWELL_SW;
00239     }
00240 
00241     /* Turn on retention regulator */
00242     MXC_PWRSEQ->reg0 |= (MXC_F_PWRSEQ_REG0_PWR_RETREGEN_RUN |
00243                          MXC_F_PWRSEQ_REG0_PWR_RETREGEN_SLP);
00244 
00245     /* Adjust settings in the retention controller for fastest wake-up time */
00246     MXC_PWRSEQ->retn_ctrl0 |= (MXC_F_PWRSEQ_RETN_CTRL0_RC_REL_CCG_EARLY |
00247                                MXC_F_PWRSEQ_RETN_CTRL0_RC_POLL_FLASH);
00248     MXC_PWRSEQ->retn_ctrl0 &= ~(MXC_F_PWRSEQ_RETN_CTRL0_RC_USE_FLC_TWK);
00249 
00250 
00251     /* Set retention controller TWake cycle count to 1us to minimize the wake-up time */
00252     /* NOTE: flash polling (...PWRSEQ_RETN_CTRL0_RC_POLL_FLASH) must be enabled before changing POR default! */
00253     MXC_PWRSEQ->retn_ctrl1 = (MXC_PWRSEQ->retn_ctrl1 & ~MXC_F_PWRSEQ_RETN_CTRL1_RC_TWK) |
00254                              (1 << MXC_F_PWRSEQ_RETN_CTRL1_RC_TWK_POS);
00255 
00256     /* Improve wake-up time by changing ROSEL to 140ns */
00257     MXC_PWRSEQ->reg3 = (1 << MXC_F_PWRSEQ_REG3_PWR_ROSEL_POS) |
00258         (1 << MXC_F_PWRSEQ_REG3_PWR_FAILSEL_POS) |
00259         (MXC_PWRSEQ->reg3 & ~(MXC_F_PWRSEQ_REG3_PWR_ROSEL |
00260            MXC_F_PWRSEQ_REG3_PWR_FLTRROSEL));
00261 
00262     /* Enable RTOS Mode: Enable 32kHz clock synchronizer to SysTick external clock input */
00263     MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_RTOS_MODE;
00264 
00265     /* Set this so all bits of PWR_MSK_FLAGS are active low to mask the corresponding flags */
00266     MXC_PWRSEQ->pwr_misc |= MXC_F_PWRSEQ_PWR_MISC_INVERT_4_MASK_BITS;
00267 
00268     /* Enable FPU on Cortex-M4, which occupies coprocessor slots 10 & 11 */
00269     /* Grant full access, per "Table B3-24 CPACR bit assignments". */
00270     /* DDI0403D "ARMv7-M Architecture Reference Manual" */
00271     SCB->CPACR |= SCB_CPACR_CP10_Msk | SCB_CPACR_CP11_Msk;
00272     __DSB();
00273     __ISB();
00274 
00275     /* Perform an initial trim of the internal ring oscillator */
00276     CLKMAN_TrimRO();
00277 
00278     SystemCoreClockUpdate();
00279     Board_Init();
00280 
00281 }