CC13xx Driver Library
rfc.c
Go to the documentation of this file.
1 /******************************************************************************
2 * Filename: rfc.c
3 * Revised: 2016-05-27 08:27:46 +0200 (Fri, 27 May 2016)
4 * Revision: 46517
5 *
6 * Description: Driver for the RF Core.
7 *
8 * Copyright (c) 2015 - 2016, Texas Instruments Incorporated
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * 1) Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * 2) Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 *
21 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 #include <driverlib/rfc.h>
40 #include <string.h>
41 
42 //*****************************************************************************
43 //
44 // Handle support for DriverLib in ROM:
45 // This section will undo prototype renaming made in the header file
46 //
47 //*****************************************************************************
48 #if !defined(DOXYGEN)
49  #undef RFCCpeIntGetAndClear
50  #define RFCCpeIntGetAndClear NOROM_RFCCpeIntGetAndClear
51  #undef RFCDoorbellSendTo
52  #define RFCDoorbellSendTo NOROM_RFCDoorbellSendTo
53  #undef RFCSynthPowerDown
54  #define RFCSynthPowerDown NOROM_RFCSynthPowerDown
55  #undef RFCRfTrimRead
56  #define RFCRfTrimRead NOROM_RFCRfTrimRead
57  #undef RFCRfTrimSet
58  #define RFCRfTrimSet NOROM_RFCRfTrimSet
59  #undef RFCRTrim
60  #define RFCRTrim NOROM_RFCRTrim
61  #undef RFCCPEPatchReset
62  #define RFCCPEPatchReset NOROM_RFCCPEPatchReset
63  #undef RFCAdi3VcoLdoVoltageMode
64  #define RFCAdi3VcoLdoVoltageMode NOROM_RFCAdi3VcoLdoVoltageMode
65 #endif
66 
67 #define RFC_RESERVED0 0x40044108
68 #define RFC_RESERVED1 0x40044114
69 #define RFC_RESERVED2 0x4004410C
70 #define RFC_RESERVED3 0x40044100
71 
72 // Position of divider value
73 #define CONFIG_MISC_ADC_DIVIDER 27
74 #define CONFIG_MISC_ADC_DIVIDER_BM 0xF8000000U
75 
76 #define _CPERAM_START 0x21000000
77 #define _PARSER_PATCH_TAB_OFFSET 0x0338
78 #define _PATCH_TAB_OFFSET 0x0340
79 #define _IRQPATCH_OFFSET 0x03BC
80 #define _PATCH_VEC_OFFSET 0x041C
81 
82 static const uint16_t rfc_defaultIrqAddr[] =
83 {
84  0x3bc3,
85  0x3a3d,
86  0x3a5d,
87  0x3a71,
88  0x0aa1,
89  0x3a8f,
90  0x3b0f,
91  0x09b3,
92  0x5e49,
93  0x0a85,
94  0x3b2f,
95  0x3b85,
96 };
97 
98 //*****************************************************************************
99 //
100 // Get and clear CPE interrupt flags
101 //
102 //*****************************************************************************
103 uint32_t
105 {
106  uint32_t ui32Ifg = HWREG(RFC_DBELL_BASE+RFC_DBELL_O_RFCPEIFG);
107 
108  do {
109  HWREG(RFC_DBELL_BASE+RFC_DBELL_O_RFCPEIFG) = ~ui32Ifg;
110  } while (HWREG(RFC_DBELL_BASE+RFC_DBELL_O_RFCPEIFG) & ui32Ifg);
111 
112  return (ui32Ifg);
113 }
114 
115 
116 //*****************************************************************************
117 //
118 // Send command to doorbell and wait for ack
119 //
120 //*****************************************************************************
121 uint32_t
122 RFCDoorbellSendTo(uint32_t pOp)
123 {
124  while(HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) != 0);
125 
126  RFCAckIntClear();
127 
128  HWREG(RFC_DBELL_BASE+RFC_DBELL_O_CMDR) = pOp;
129 
130  while(!HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG));
131  RFCAckIntClear();
132 
133  return(HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA));
134 }
135 
136 
137 //*****************************************************************************
138 //
139 // Turn off synth, NOTE: Radio will no longer respond to commands!
140 //
141 //*****************************************************************************
142 void
144 {
145  // Disable CPE clock, enable FSCA clock. NOTE: Radio will no longer respond to commands!
146  HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = (HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) & ~RFC_PWR_PWMCLKEN_CPE_M) | RFC_PWR_PWMCLKEN_FSCA_M;
147 
148  (*((volatile unsigned long *)(RFC_RESERVED0))) = 3;
149  (*((volatile unsigned long *)(RFC_RESERVED1))) = 0x1030;
150  (*((volatile unsigned long *)(RFC_RESERVED2))) = 1;
151  (*((volatile unsigned long *)(RFC_RESERVED1))) = 0x50;
152  (*((volatile unsigned long *)(RFC_RESERVED2))) = 1;
153  (*((volatile unsigned long *)(RFC_RESERVED1))) = 0x650;
154  (*((volatile unsigned long *)(RFC_RESERVED2))) = 1;
155  (*((volatile unsigned long *)(RFC_RESERVED3))) = 1;
156 }
157 
158 
159 //*****************************************************************************
160 //
161 // Read RF Trim from flash using the CM3
162 //
163 //*****************************************************************************
164 void RFCRfTrimRead(rfc_radioOp_t *pOpSetup, rfTrim_t* pRfTrim)
165 {
166  int divider;
167  // Check which setup command is used
168  switch (pOpSetup->commandNo)
169  {
170  case CMD_RADIO_SETUP:
171  divider = ((rfc_CMD_RADIO_SETUP_t *)pOpSetup)->loDivider;
172  break;
174  divider = ((rfc_CMD_PROP_RADIO_DIV_SETUP_t *)pOpSetup)->loDivider;
175  break;
176  default:
177  divider = 0; // Use 2.4 GHz
178  break;
179  }
180 
181  // Read trim from FCFG1
182  pRfTrim->configIfAdc = HWREG(FCFG1_BASE + FCFG1_O_CONFIG_IF_ADC);
183  switch (divider)
184  {
185  case 5:
190  break;
191 
192  case 6:
197  break;
198 
199  case 10:
204  break;
205 
206  case 12:
211  break;
212 
213  case 15:
218  break;
219 
220  case 30:
225  break;
226 
227  default:
229  pRfTrim->configSynth = HWREG(FCFG1_BASE + FCFG1_O_CONFIG_SYNTH);
230  // Make sure configMiscAdc is not 0 by setting an unused bit to 1
233  break;
234  }
235 }
236 
237 
238 //*****************************************************************************
239 //
240 // Check Override RTrim vs FCFG RTrim
241 //
242 //*****************************************************************************
243 void RFCRTrim(rfc_radioOp_t *pOpSetup)
244 {
245  int32_t divider;
246  uint32_t fcfg1_rtrim;
247  uint32_t *pOverride;
248  int32_t override_index;
249  uint32_t override_value;
250  uint32_t override_rtrim = 0;
251 
252  // Check which setup command is used
253  switch (pOpSetup->commandNo)
254  {
255  case CMD_RADIO_SETUP:
256  divider = ((rfc_CMD_RADIO_SETUP_t *)pOpSetup)->loDivider;
257  pOverride = ((rfc_CMD_RADIO_SETUP_t *)pOpSetup)->pRegOverride;
258  break;
260  divider = 2;
261  pOverride = ((rfc_CMD_PROP_RADIO_SETUP_t *)pOpSetup)->pRegOverride;
262  break;
264  divider = ((rfc_CMD_PROP_RADIO_DIV_SETUP_t *)pOpSetup)->loDivider;
265  pOverride = ((rfc_CMD_PROP_RADIO_DIV_SETUP_t *)pOpSetup)->pRegOverride;
266  break;
267  default:
268  return;
269  }
270 
271  if (pOverride == 0)
272  {
273  // Did not find override, return
274  return;
275  }
276 
277 
278  // Search top 5 overrides for RTRIM
279  for(override_index = 0; override_index < 5; override_index++)
280  {
281  override_value = pOverride[override_index];
282  if((override_value & 0xFFFF) == 0x4038)
283  {
284  override_rtrim = (override_value & 0xF0000) >> 16;
285  break;
286  }
287  }
288 
289  if (override_rtrim == 0)
290  {
291  // Did not find override, return
292  return;
293  }
294 
295  // Read trim from FCFG1
296  switch (divider)
297  {
298  case 2:
299  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC)
301  break;
302  case 5:
303  // Legacy
304  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_MISC_OTP_DATA)
306  break;
307  case 6:
308  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC_DIV6)
310  break;
311  case 10:
312  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC_DIV10)
314  break;
315  case 12:
316  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC_DIV12)
318  break;
319  case 15:
320  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC_DIV15)
322  break;
323  case 30:
324  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC_DIV30)
326  break;
327  default:
328  fcfg1_rtrim = (HWREG(FCFG1_BASE + FCFG1_O_CONFIG_MISC_ADC)
330  break;
331  }
332 
333  // Check for early samples
334  if(fcfg1_rtrim == 0xF)
335  {
336  // set default
337  switch (divider)
338  {
339  case 5:
340  case 10:
341  case 15:
342  case 30:
343  pOverride[override_index] = (override_value & 0xFFF0FFFF) | (0x7 << 16);
344  break;
345  case 2:
346  case 6:
347  case 12:
348  default:
349  pOverride[override_index] = (override_value & 0xFFF0FFFF) | (0x4 << 16);
350  break;
351  }
352  }
353  else
354  {
355  // Test Override vs FCFG1 limit.
356  if(override_rtrim >= fcfg1_rtrim)
357  {
358  // Do nothing
359  ;
360  }
361  else
362  {
363  // Set override to FCFG1 limit value
364  pOverride[override_index] = (override_value & 0xFFF0FFFF) | (fcfg1_rtrim << 16);
365  }
366  }
367 }
368 
369 
370 //*****************************************************************************
371 //
372 // Write preloaded RF trim values to CM0
373 //
374 //*****************************************************************************
375 void RFCRfTrimSet(rfTrim_t* pRfTrim)
376 {
377  memcpy((void*)&HWREG(0x21000018), (void*)pRfTrim, sizeof(rfTrim_t));
378 }
379 
380 
381 //*****************************************************************************
382 //
383 // Reset previously patched CPE RAM to a state where it can be patched again
384 //
385 //*****************************************************************************
387 {
388  uint8_t *pPatchTab = (uint8_t *) (_CPERAM_START + _PARSER_PATCH_TAB_OFFSET);
389  uint32_t *pIrqPatch = (uint32_t *) (_CPERAM_START + _IRQPATCH_OFFSET);
390 
391  memset(pPatchTab, 0xFF, _IRQPATCH_OFFSET - _PARSER_PATCH_TAB_OFFSET);
392 
393  int i;
394  for (i = 0; i < sizeof(rfc_defaultIrqAddr)/sizeof(rfc_defaultIrqAddr[0]); i++)
395  {
396  pIrqPatch[i * 2 + 1] = rfc_defaultIrqAddr[i];
397  }
398 }
399 
400 
401 //*****************************************************************************
402 //
403 // Function to set VCOLDO reference to voltage mode
404 //
405 //*****************************************************************************
406 void RFCAdi3VcoLdoVoltageMode(bool bEnable)
407 {
408  if (bEnable)
409  {
410  // First make sure the REFSYSCTL0 mux output is not further muxed out
411  HWREGB(0x40086200) = 0x0;
412  // Set the REFSYSCTL0 mux as desired for VCOLDO voltage mode
414  }
415  else
416  {
417  // Revert the mux override
419  }
420 }
421 
422 
423 
424 //*****************************************************************************
425 //
426 // Handle support for DriverLib in ROM:
427 // This section will undo prototype renaming made in the header file
428 //
429 //*****************************************************************************
430 #if !defined(DOXYGEN)
431  #undef RFCCpeIntGetAndClear
432  #define RFCCpeIntGetAndClear NOROM_RFCCpeIntGetAndClear
433  #undef RFCDoorbellSendTo
434  #define RFCDoorbellSendTo NOROM_RFCDoorbellSendTo
435  #undef RFCSynthPowerDown
436  #define RFCSynthPowerDown NOROM_RFCSynthPowerDown
437  #undef RFCRfTrimRead
438  #define RFCRfTrimRead NOROM_RFCRfTrimRead
439  #undef RFCRfTrimSet
440  #define RFCRfTrimSet NOROM_RFCRfTrimSet
441  #undef RFCRTrim
442  #define RFCRTrim NOROM_RFCRTrim
443  #undef RFCCPEPatchReset
444  #define RFCCPEPatchReset NOROM_RFCCPEPatchReset
445  #undef RFCAdi3VcoLdoVoltageMode
446  #define RFCAdi3VcoLdoVoltageMode NOROM_RFCAdi3VcoLdoVoltageMode
447 #endif
448 
449 // See rfc.h for implementation
#define RFC_RESERVED0
Definition: rfc.c:67
uint32_t configSynth
Definition: rfc.h:75
static const uint16_t rfc_defaultIrqAddr[]
Definition: rfc.c:82
#define CMD_PROP_RADIO_SETUP
Definition: rf_prop_cmd.h:447
struct __RFC_STRUCT rfc_CMD_PROP_RADIO_DIV_SETUP_s rfc_CMD_PROP_RADIO_DIV_SETUP_t
Definition: rf_prop_cmd.h:67
#define _IRQPATCH_OFFSET
Definition: rfc.c:79
struct __RFC_STRUCT rfc_CMD_RADIO_SETUP_s rfc_CMD_RADIO_SETUP_t
Definition: rf_common_cmd.h:62
#define CMD_PROP_RADIO_DIV_SETUP
Definition: rf_prop_cmd.h:536
struct __RFC_STRUCT rfc_radioOp_s rfc_radioOp_t
Definition: rf_common_cmd.h:60
#define CONFIG_MISC_ADC_DIVIDER_BM
Definition: rfc.c:74
void RFCRfTrimSet(rfTrim_t *pRfTrim)
Write preloaded RF trim values to CM0.
Definition: rfc.c:375
static void RFCAckIntClear(void)
Clear interrupt flags.
Definition: rfc.h:318
Definition: rfc.h:72
uint32_t RFCCpeIntGetAndClear(void)
Get and clear CPE interrupt flags.
Definition: rfc.c:104
#define CONFIG_MISC_ADC_DIVIDER
Definition: rfc.c:73
#define RFC_RESERVED3
Definition: rfc.c:70
struct __RFC_STRUCT rfc_CMD_PROP_RADIO_SETUP_s rfc_CMD_PROP_RADIO_SETUP_t
Definition: rf_prop_cmd.h:66
uint32_t configMiscAdc
Definition: rfc.h:76
#define RFC_RESERVED2
Definition: rfc.c:69
void RFCRTrim(rfc_radioOp_t *pOpSetup)
Check Override RTrim vs FCFG RTrim.
Definition: rfc.c:243
uint32_t configRfFrontend
Definition: rfc.h:74
#define CMD_RADIO_SETUP
void RFCCPEPatchReset(void)
Reset previously patched CPE RAM to a state where it can be patched again.
Definition: rfc.c:386
uint32_t configIfAdc
Definition: rfc.h:73
uint32_t RFCDoorbellSendTo(uint32_t pOp)
Send command to doorbell and wait for ack.
Definition: rfc.c:122
void RFCAdi3VcoLdoVoltageMode(bool bEnable)
Function to set VCOLDO reference to voltage mode.
Definition: rfc.c:406
void RFCRfTrimRead(rfc_radioOp_t *pOpSetup, rfTrim_t *pRfTrim)
Read RF trim from flash using CM3.
Definition: rfc.c:164
#define _CPERAM_START
Definition: rfc.c:76
#define _PARSER_PATCH_TAB_OFFSET
Definition: rfc.c:77
void RFCSynthPowerDown()
Turn off synth, NOTE: Radio will no longer respond to commands!
Definition: rfc.c:143
#define RFC_RESERVED1
Definition: rfc.c:68