CC26xx Driver Library
[setup.h] Setup

Functions

void SetupTrimDevice (void)
 Performs the necessary trim of the device which is not done in ROM boot code. More...
 

Detailed Description

This module contains functions for device setup which is not done in boot code.

Function Documentation

§ SetupTrimDevice()

void SetupTrimDevice ( void  )

Performs the necessary trim of the device which is not done in ROM boot code.

This function should only execute coming from ROM boot.

The following is handled by this function:

  • Checks if the driverlib variant used by the application is supported by the device. Execution is halted in case of unsupported driverlib variant.
  • Configures VIMS cache mode based on setting in CCFG.
  • Configures functionalities like DCDC and XOSC dependent on startup modes like cold reset, wakeup from shutdown and wakeup from from powerdown.
  • Configures VIMS power domain control.
  • Configures optimal wait time for flash FSM in cases where flash pump wakes up from sleep.
Note
The current implementation does not take soft reset into account. However, it does no damage to execute it again. It only consumes time.
This function is called by the compiler specific device startup codes that are integrated in the SimpleLink SDKs for CC13xx/CC26XX devices.
Returns
None
126 {
127  uint32_t ui32Fcfg1Revision;
128  uint32_t ui32AonSysResetctl;
129 
130  // Get layout revision of the factory configuration area
131  // (Handle undefined revision as revision = 0)
132  ui32Fcfg1Revision = HWREG(FCFG1_BASE + FCFG1_O_FCFG1_REVISION);
133  if ( ui32Fcfg1Revision == 0xFFFFFFFF ) {
134  ui32Fcfg1Revision = 0;
135  }
136 
137  // This driverlib version and setup file is for the CC13x4, CC26x4 chips.
138  // Halt if violated
140 
141  // Select correct CACHE mode and set correct CACHE configuration
142 #if ( CCFG_BASE == CCFG_BASE_DEFAULT )
144 #else
145  NOROM_SetupSetCacheModeAccordingToCcfgSetting();
146 #endif
147 
148  // 1. Check for powerdown
149  // 2. Check for shutdown
150  // 3. Assume cold reset if none of the above.
151  //
152  // It is always assumed that the application will freeze the latches in
153  // AON_IOC when going to powerdown in order to retain the values on the IOs.
154  //
155  // NB. If this bit is not cleared before proceeding to powerdown, the IOs
156  // will all default to the reset configuration when restarting.
157  if( ! ( HWREG( AON_IOC_BASE + AON_IOC_O_IOCLATCH ) & AON_IOC_IOCLATCH_EN ))
158  {
159  // NB. This should be calling a ROM implementation of required trim and
160  // compensation
161  // e.g. TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown()
163  }
164  // Check for shutdown
165  //
166  // When device is going to shutdown the hardware will automatically clear
167  // the SLEEPDIS bit in the SLEEP register in the AON_PMCTL module.
168  // It is left for the application to assert this bit when waking back up,
169  // but not before the desired IO configuration has been re-established.
170  else if( ! ( HWREG( AON_PMCTL_BASE + AON_PMCTL_O_SLEEPCTL ) & AON_PMCTL_SLEEPCTL_IO_PAD_SLEEP_DIS ))
171  {
172  // NB. This should be calling a ROM implementation of required trim and
173  // compensation
174  // e.g. TrimAfterColdResetWakeupFromShutDown() -->
175  // TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown();
176  TrimAfterColdResetWakeupFromShutDown(ui32Fcfg1Revision);
178  }
179  else
180  {
181  // Consider adding a check for soft reset to allow debugging to skip
182  // this section!!!
183  //
184  // NB. This should be calling a ROM implementation of required trim and
185  // compensation
186  // e.g. TrimAfterColdReset() -->
187  // TrimAfterColdResetWakeupFromShutDown() -->
188  // TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown()
190  TrimAfterColdResetWakeupFromShutDown(ui32Fcfg1Revision);
192 
193  }
194 
195  // Set VIMS power domain control.
196  // PDCTL1VIMS = 0 ==> VIMS power domain is only powered when CPU power domain is powered
197  HWREG( PRCM_BASE + PRCM_O_PDCTL1VIMS ) = 0;
198 
199  // And finally at the end of the flash boot process:
200  // SET BOOT_DET bits in AON_PMCTL to 3 if already found to be 1
201  // Note: The BOOT_DET_x_CLR/SET bits must be manually cleared
202  if ((( HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) &
203  ( AON_PMCTL_RESETCTL_BOOT_DET_1_M | AON_PMCTL_RESETCTL_BOOT_DET_0_M )) >>
204  AON_PMCTL_RESETCTL_BOOT_DET_0_S ) == 1 )
205  {
206  ui32AonSysResetctl = ( HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) &
207  ~( AON_PMCTL_RESETCTL_BOOT_DET_1_CLR_M | AON_PMCTL_RESETCTL_BOOT_DET_0_CLR_M |
208  AON_PMCTL_RESETCTL_BOOT_DET_1_SET_M | AON_PMCTL_RESETCTL_BOOT_DET_0_SET_M | AON_PMCTL_RESETCTL_MCU_WARM_RESET_M ));
209  HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) = ui32AonSysResetctl | AON_PMCTL_RESETCTL_BOOT_DET_1_SET_M;
210  HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) = ui32AonSysResetctl;
211  }
212 
213  // Reset the RTC
214  AONRTCReset();
215  // Configure the combined event
216  IntPendClear(INT_AON_RTC_COMB);
218  // Start the RTC
219  AONRTCEnable();
220 
222  {
223  /* Set SubSecInc to 31.250 kHz since we start up on RCOSC_HF_DLF. The
224  * rom startup code leaves this at the default 32.768 kHz but that is
225  * only accurate once we actually switch to XOSC_LF. Once the
226  * oscillator combined interrupt triggers after we switch to the target
227  * clock, we will configure SubSecInc back to 32.768 kHz.
228  *
229  * There is no need to update SubSecInc dynamically for other LF clock
230  * sources.
231  * - RCOSC_LF starts on RCOSC_HF-derived but switches fast enough that
232  * we do not accumulate any real-time clock drift before switching.
233  * - External LF is correctly set and requires no switching.
234  * - XOSC_HF-derived does not change LF clock frequencies.
235  */
237  }
238 
239  // Make sure there are no ongoing VIMS mode change when leaving SetupTrimDevice()
240  // (There should typically be no wait time here, but need to be sure)
241  while ( HWREG( VIMS_BASE + VIMS_O_STAT ) & VIMS_STAT_MODE_CHANGING ) {
242  // Do nothing - wait for an eventual ongoing mode change to complete.
243  }
244 
245  // Configure the NONSECWRn registers to allow manipulation of
246  // ADI_3_REFSYS_DCDCCTL5_IPEAK and ADI_3_REFSYS_DCDCCTL5_DITHER from the
247  // non-secure side. This is required by the radio for proper operation.
248  // The ADI_3_REFSYS_O_DCDCCTL5 register byte-offset is divided by two
249  // since the the ADDR field is encoded as a half-word index
250 
251  // Dither disabled, IPEAK = 0
252  HWREG( ADI3_BASE + ADI_O_NONSECWR0) = (( 0x00 << ADI_NONSECWR0_DATA_S) & ADI_NONSECWR0_DATA_M ) |
253  ((( ( ADI_3_REFSYS_O_DCDCCTL5) ) << ADI_NONSECWR0_ADDR_S ) & ADI_NONSECWR0_ADDR_M) |
254  (( 0x0F << ADI_NONSECWR0_WR_MASK_S) & ADI_NONSECWR0_WR_MASK_M);
255 
256  // Dither enabled, IPEAK = 0
257  HWREG( ADI3_BASE + ADI_O_NONSECWR1) = (( 0x08 << ADI_NONSECWR1_DATA_S) & ADI_NONSECWR1_DATA_M ) |
258  ((( ( ADI_3_REFSYS_O_DCDCCTL5) ) << ADI_NONSECWR1_ADDR_S ) & ADI_NONSECWR1_ADDR_M) |
259  (( 0x0F << ADI_NONSECWR1_WR_MASK_S) & ADI_NONSECWR1_WR_MASK_M);
260 
261  // Dither disabled, IPEAK = 3
262  HWREG( ADI3_BASE + ADI_O_NONSECWR2) = (( 0x03 << ADI_NONSECWR2_DATA_S) & ADI_NONSECWR2_DATA_M ) |
263  ((( ( ADI_3_REFSYS_O_DCDCCTL5) ) << ADI_NONSECWR2_ADDR_S ) & ADI_NONSECWR2_ADDR_M) |
264  (( 0x0F << ADI_NONSECWR2_WR_MASK_S) & ADI_NONSECWR2_WR_MASK_M);
265 
266  // Dither disabled, IPEAK = 7
267  HWREG( ADI3_BASE + ADI_O_NONSECWR3) = (( 0x07 << ADI_NONSECWR3_DATA_S) & ADI_NONSECWR3_DATA_M ) |
268  ((( ( ADI_3_REFSYS_O_DCDCCTL5) ) << ADI_NONSECWR3_ADDR_S ) & ADI_NONSECWR3_ADDR_M) |
269  (( 0x0F << ADI_NONSECWR3_WR_MASK_S) & ADI_NONSECWR3_WR_MASK_M);
270 
271  // Configure Sensor Controller access to TDC clock control
272  // Allow read and write ACLK_TDC_SRC_SEL and ACLK_REF_SRC_SEL fields in
273  // DDI_0_OSC_O_CTL0 register.
274  // The ADDR field is encoded as a half-word index. So we need to divide the
275  // regular byte-offset by two.
276  // Use NONSECDDIACC3 because if ADDR is 0 for multiple NONSECDDIACCn,
277  // only the highest NONSECDIACCn takes effect. 0 is the reset value for
278  // ADDR and DDI_0_OSC_O_CTL0 has an ADDR offset of 0. So to access this
279  // Register, we should always aim to use the highest NONSECDDIACCn.
280  HWREG( AUX_SCE_BASE + AUX_SCE_O_NONSECDDIACC3) = AUX_SCE_NONSECDDIACC3_RD_EN |
281  (( ( DDI_0_OSC_O_CTL0 / 2 ) << AUX_SCE_NONSECDDIACC3_ADDR_S ) & AUX_SCE_NONSECDDIACC3_ADDR_M ) |
282  (( DDI_0_OSC_CTL0_ACLK_TDC_SRC_SEL_M | DDI_0_OSC_CTL0_ACLK_REF_SRC_SEL_M ) & AUX_SCE_NONSECDDIACC3_WR_MASK_M );
283 
284  // Configure Sensor Controller access to read the XOSC_HF frequency good
285  // signal.
286  // We want to read DDI_0_OSC_STAT2_XOSC_HF_FREQGOOD.
287  // The ADDR field is encoded as a half-word index. So we need to divide the
288  // regular byte-offset by two.
289  // No need for the WR mask since we only want to read from the register.
290  HWREG( AUX_SCE_BASE + AUX_SCE_O_NONSECDDIACC2) = AUX_SCE_NONSECDDIACC2_RD_EN |
291  (( ( DDI_0_OSC_O_STAT2 / 2 ) << AUX_SCE_NONSECDDIACC2_ADDR_S ) & AUX_SCE_NONSECDDIACC2_ADDR_M);
292 
293 
294  // Configure Sensor Controller access to COMPB 32 kHz clock enable
295  // We want to read and write DDI_0_OSC_ATESTCTL_SCLK_LF_AUX_EN.
296  // This is a 16-bit write, so we need to add to the address offset since
297  // DDI_0_OSC_ATESTCTL_SCLK_LF_AUX_EN is in the upper half of the register.
298  // The ADDR field is encoded as a half-word index. So we need to divide the
299  // regular byte-offset by two.
300  // The mask needs to be shifted down because the original register field
301  // mask is provided as a 32-bit mask.
302  HWREG( AUX_SCE_BASE + AUX_SCE_O_NONSECDDIACC1) = AUX_SCE_NONSECDDIACC1_RD_EN |
303  ((( ( DDI_0_OSC_O_ATESTCTL + 2 ) / 2 ) << AUX_SCE_NONSECDDIACC1_ADDR_S ) & AUX_SCE_NONSECDDIACC1_ADDR_M) |
304  (( DDI_0_OSC_ATESTCTL_SCLK_LF_AUX_EN_M >> 16 ) & AUX_SCE_NONSECDDIACC1_WR_MASK_M);
305 
306  // Enable output of RTC clock for Radio Timer Synchronization
307  HWREG(AON_RTC_BASE + AON_RTC_O_CTL) |= AON_RTC_CTL_RTC_UPD_EN_M;
308 }
#define AON_RTC_CH1
Definition: aon_rtc.h:93
void IntPendClear(uint32_t ui32Interrupt)
Unpends an interrupt.
Definition: interrupt.c:441
void ThisLibraryIsFor_CC13x4_CC26x4_HaltIfViolated(void)
Verifies that current chip is CC13x4 or CC26x4 and never returns if violated.
Definition: chipinfo.c:196
#define AON_RTC_CH2
Definition: aon_rtc.h:94
#define CCFGREAD_SCLK_LF_OPTION_XOSC_LF
Definition: ccfgread.h:116
static void AONRTCCombinedEventConfig(uint32_t ui32Channels)
Configure the source of the combined event.
Definition: aon_rtc.h:335
static void TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown(void)
Trims to be applied when coming from POWER_DOWN (also called when coming from SHUTDOWN and PIN_RESET)...
Definition: setup.c:319
static void AONRTCReset(void)
Reset the RTC.
Definition: aon_rtc.h:209
#define AON_RTC_CH0
Definition: aon_rtc.h:92
static uint32_t CCFGRead_SCLK_LF_OPTION(void)
Read SCLK_LF_OPTION from CCFG.
Definition: ccfgread.h:132
void SetupSetAonRtcSubSecInc(uint32_t subSecInc)
Doing the tricky stuff needed to enter new RTCSUBSECINC value.
Definition: setup_rom.c:926
static void TrimAfterColdResetWakeupFromShutDown(uint32_t ui32Fcfg1Revision)
Trims to be applied when coming from SHUTDOWN (also called when coming from PIN_RESET).
Definition: setup.c:335
static void AONRTCEnable(void)
Enable the RTC.
Definition: aon_rtc.h:172
void SetupSetCacheModeAccordingToCcfgSetting(void)
Set correct VIMS_MODE according to CCFG setting (CACHE or GPRAM)
Definition: setup_rom.c:881
#define SUBSECINC_31250_HZ
Definition: setup.c:103
static void TrimAfterColdReset(void)
Trims to be applied when coming from PIN_RESET.
Definition: setup.c:435
Here is the call graph for this function: