1 //*****************************************************************************
2 //
3 //! @file am_hal_ble.c
4 //!
5 //! @brief HAL Functions for the BLE Interface.
6 //!
7 //! @addtogroup BLE3 BLE - BLE functions
8 //! @ingroup apollo3_hal
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include <string.h>
51 #include "am_mcu_apollo.h"
52 #include "am_hal_ble_patch.h"
53 #include "am_hal_ble_patch_b0.h"
54
55 //*****************************************************************************
56 //
57 // Globals
58 //
59 //*****************************************************************************
60 am_hal_ble_state_t g_sBLEState[AM_REG_BLEIF_NUM_MODULES];
61
62 //*****************************************************************************
63 //
64 //! Helper macros for rev B0 parts.
65 //
66 //*****************************************************************************
67 #define BLEIF_INTSTAT_BLECSSTATN_Msk BLEIF_INTSTAT_B2MSHUTDN_Msk
68 #define BLEIF_INTSTAT_BLECIRQN_Msk BLEIF_INTSTAT_B2MACTIVE_Msk
69
70 #define SKIP_FALLING_EDGES 0
71
72 //*****************************************************************************
73 //
74 //! SPI "options"
75 //!
76 //! These values affect the behavior of the BLE HAL in regards to the SPI bus,
77 //! but end users aren't likely to need to modify them. They are collected here
78 //! for testing and debugging purposes.
79 //
80 //*****************************************************************************
81 //! The amount of extra delay to add between successive SPI TX packets (in
82 //! microseconds).
83 #define AM_BLE_TX_PACKET_SPACING_US 1
84
85 //! The BLE core takes a little while to wake up from a fresh boot, which means
86 //! that the patch_apply function might time-out on the first few tries. Set
87 //! this variable to let it try again for a finite number of trials.
88 #define AM_BLE_NUM_PATCH_TRIALS 5000
89
90 //! Patch complete can also take some time.
91 #define AM_BLE_NUM_PATCH_CMP_TRIALS 5000
92
93 //! How long the MCU should wait for SPI_STATUS before assuming the BLE core is
94 //! busy (measured in 10 us increments).
95 #define AM_BLE_STATUS_TIMEOUT 300
96
97 //*****************************************************************************
98 //
99 //! Private types.
100 //
101 //*****************************************************************************
102 #define AM_HAL_MAGIC_BLE 0x775230
103
104 #define AM_HAL_BLE_CHK_HANDLE(h) \
105 ((h) && ((am_hal_handle_prefix_t *)(h))->s.bInit \
106 && (((am_hal_handle_prefix_t *)(h))->s.magic == AM_HAL_MAGIC_BLE))
107
108 //*****************************************************************************
109 //
110 //! BLE Core maximum patch packet size.
111 //
112 //! Specified as part of the protocol.
113 //
114 //*****************************************************************************
115 #define MAX_PATCH_PACKET_LEN 0x80
116
117 //*****************************************************************************
118 //
119 //! Some of the NationZ register addresses are different between A1/A2 and B0.
120 //
121 //*****************************************************************************
122
123 #define AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_A1 0x20006054
124 #define AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_A1 0x20006070
125 #define AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_A1 0x20006038
126 #define AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1 (0x200067b8 + 0x0c)
127
128 #define AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_B0 0x20006858
129 #define AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_B0 0x20006874
130 #define AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_B0 0x20006838
131 #define AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0 (0x20006e0c + 0x0c)
132
133 //*****************************************************************************
134 //
135 //! Static function prototypes.
136 //
137 //*****************************************************************************
138 static bool am_hal_ble_bus_lock(am_hal_ble_state_t *pBle);
139 static void am_hal_ble_bus_release(am_hal_ble_state_t *pBle);
140 static uint32_t am_hal_ble_fifo_drain(void *pHandle);
141 static void am_hal_ble_fifo_read(void *pHandle, uint32_t *pui32Data, uint32_t ui32NumBytes);
142 static bool am_hal_ble_check_status(am_hal_ble_state_t *pBle);
143 static bool am_hal_ble_check_irq(am_hal_ble_state_t *pBle);
144 static uint32_t am_hal_ble_cmd_write(void *pHandle, am_hal_ble_transfer_t *psTransfer);
145 static uint32_t am_hal_ble_load_modex_trim_set(void *pHandle);
146 static uint32_t nonblocking_write(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer);
147 static uint32_t nonblocking_read(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer);
148 static uint8_t am_hal_ble_read_trimdata_from_info1(void);
149 static uint32_t am_util_ble_platform_reset(void *pHandle);
150
151 //*****************************************************************************
152 //
153 //! Look up Table for NZ CRC16 generation
154 //
155 //*****************************************************************************
156 static const uint16_t ccitt_table[] =
157 {
158 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
159 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
160 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
161 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
162 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
163 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
164 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
165 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
166 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
167 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
168 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
169 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
170 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
171 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
172 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
173 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
174 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
175 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
176 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
177 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
178 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
179 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
180 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
181 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
182 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
183 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
184 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
185 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
186 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
187 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
188 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
189 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
190 };
191
192 //*****************************************************************************
193 //
194 //! Helper macros for delays.
195 //
196 //*****************************************************************************
197 #define delay_ms(ms) am_hal_flash_delay(FLASH_CYCLES_US(1000 * (ms)))
198 #define delay_us(us) am_hal_flash_delay(FLASH_CYCLES_US(us))
199
200 #define WHILE_TIMEOUT_MS(expr, timeout, error) \
201 { \
202 uint32_t ui32Timeout = 0; \
203 while (expr) \
204 { \
205 if (ui32Timeout >= (timeout * 1000)) \
206 { \
207 return error; \
208 } \
209 \
210 delay_us(1); \
211 ui32Timeout++; \
212 } \
213 }
214
215 #define WHILE_TIMEOUT_MS_BREAK(expr, timeout, error) \
216 { \
217 uint32_t ui32Timeout = 0; \
218 while (expr) \
219 { \
220 if (ui32Timeout >= (timeout * 1000)) \
221 { \
222 break; \
223 } \
224 \
225 delay_us(1); \
226 ui32Timeout++; \
227 } \
228 }
229
230 //*****************************************************************************
231 //
232 //! @brief Helper function for checking BLE data.
233 //!
234 //! @param b1
235 //! @param b2
236 //! @param len
237 //! @return true
238 //! @return false
239 //
240 //*****************************************************************************
241 static bool
buffer_compare(void * b1,void * b2,uint32_t len)242 buffer_compare(void *b1, void *b2, uint32_t len)
243 {
244 uint8_t *p1 = b1;
245 uint8_t *p2 = b2;
246
247 for (uint32_t i = 0; i < len; i++)
248 {
249 if (p1[i] != p2[i])
250 {
251 return false;
252 }
253 }
254
255 return true;
256 }
257
258 //*****************************************************************************
259 //
260 //! @brief Helper function for CRC caculation of BLE patch.
261 //!
262 //! @param pui8Data
263 //! @param len
264 //! @return uint16_t
265 //
266 //*****************************************************************************
267 static uint16_t
am_hal_ble_crc_nz(uint8_t * pui8Data,uint32_t len)268 am_hal_ble_crc_nz(uint8_t *pui8Data, uint32_t len)
269 {
270 uint16_t ui16CurValue = 0;
271 uint32_t i;
272
273 for (i = 0; i < len; i++)
274 {
275 ui16CurValue = ccitt_table[(((uint8_t)(ui16CurValue >> 8)) ^ pui8Data[i]) & 0xFF] ^ (ui16CurValue << 8);
276 }
277
278 return ((ui16CurValue ^ 0) & ((1 << 16) - 1));
279 }
280
281 //*****************************************************************************
282 //!
283 //! @brief Default options for the BLE module.
284 //!
285 //*****************************************************************************
286 const am_hal_ble_config_t am_hal_ble_default_config =
287 {
288 //! Configure the HCI interface clock for 6 MHz
289 .ui32SpiClkCfg = AM_HAL_BLE_HCI_CLK_DIV8,
290
291 //! Set HCI read and write thresholds to 32 bytes each.
292 .ui32ReadThreshold = 32,
293 .ui32WriteThreshold = 32,
294
295 //! The MCU will supply the clock to the BLE core.
296 .ui32BleClockConfig = AM_HAL_BLE_CORE_MCU_CLK,
297
298 //! Default settings for expected BLE clock drift.
299 .ui32ClockDrift = 0,
300 .ui32SleepClockDrift = 50,
301
302 //! Default setting: AGC Enabled
303 .bAgcEnabled = true,
304
305 //! Default setting: Sleep Algo enabled
306 .bSleepEnabled = true,
307
308 //! Apply the default patches when am_hal_ble_boot() is called.
309 .bUseDefaultPatches = true,
310 };
311
312 //*****************************************************************************
313 //
314 // Function for controlling the WAKE signal.
315 //
316 //*****************************************************************************
317 uint32_t
am_hal_ble_wakeup_set(void * pHandle,uint32_t ui32Mode)318 am_hal_ble_wakeup_set(void *pHandle, uint32_t ui32Mode)
319 {
320 am_hal_ble_state_t *pBle = pHandle;
321
322 //
323 // Check the handle.
324 //
325 if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
326 {
327 return AM_HAL_STATUS_INVALID_HANDLE;
328 }
329
330 // am_hal_debug_gpio_set(BLE_DEBUG_TRACE_08);
331
332 if ( ui32Mode )
333 {
334 BLEIFn(pBle->ui32Module)->BLECFG_b.WAKEUPCTL = BLEIF_BLECFG_WAKEUPCTL_ON;
335 am_hal_debug_gpio_set(BLE_DEBUG_TRACE_08);
336 }
337 else
338 {
339 #ifndef AM_DISABLE_BLE_SLEEP
340 BLEIFn(pBle->ui32Module)->BLECFG_b.WAKEUPCTL = BLEIF_BLECFG_WAKEUPCTL_OFF;
341 am_hal_debug_gpio_clear(BLE_DEBUG_TRACE_08);
342 #endif
343 }
344
345 return AM_HAL_STATUS_SUCCESS;
346
347 // am_hal_debug_gpio_clear(BLE_DEBUG_TRACE_08);
348 }
349
350 //*****************************************************************************
351 //
352 // Buffer for patch data.
353 //
354 //*****************************************************************************
355 am_hal_ble_buffer(128 + 4) g_psPatchBuffer;
356
357 //*****************************************************************************
358 //
359 // Initialize the global variables associated with a BLE module, and return its
360 // handle.
361 //
362 //*****************************************************************************
363 uint32_t
am_hal_ble_initialize(uint32_t ui32Module,void ** ppHandle)364 am_hal_ble_initialize(uint32_t ui32Module, void **ppHandle)
365 {
366 //
367 // Check the arguments.
368 //
369 if (ui32Module >= AM_REG_BLEIF_NUM_MODULES)
370 {
371 return AM_HAL_STATUS_OUT_OF_RANGE;
372 }
373
374 if (!ppHandle)
375 {
376 return AM_HAL_STATUS_INVALID_ARG;
377 }
378
379 //
380 // Check if the handle is unallocated.
381 //
382 if (g_sBLEState[ui32Module].prefix.s.bInit)
383 {
384 return AM_HAL_STATUS_INVALID_OPERATION;
385 }
386
387 //
388 // Initialize the handle.
389 //
390 memset(&g_sBLEState[ui32Module].sCurrentTransfer, 0, sizeof(am_hal_ble_transfer_t));
391 memset(&g_sBLEState[ui32Module].sSavedTransfer, 0, sizeof(am_hal_ble_transfer_t));
392
393 g_sBLEState[ui32Module].prefix.s.bInit = true;
394 g_sBLEState[ui32Module].prefix.s.magic = AM_HAL_MAGIC_BLE;
395 g_sBLEState[ui32Module].ui32Module = ui32Module;
396 g_sBLEState[ui32Module].ui32TransferIndex = 0;
397 g_sBLEState[ui32Module].bPatchComplete = 0;
398 g_sBLEState[ui32Module].bContinuePacket = 0;
399 g_sBLEState[ui32Module].bSavedPacket = 0;
400 g_sBLEState[ui32Module].bBusy = 0;
401 g_sBLEState[ui32Module].bCmdComplete = 0;
402 g_sBLEState[ui32Module].bDmaComplete = 0;
403 g_sBLEState[ui32Module].bFlowControlComplete = 0;
404 g_sBLEState[ui32Module].bUseDefaultPatches = false;
405
406 //
407 // Pass the handle back to the caller.
408 //
409 *ppHandle = &g_sBLEState[ui32Module];
410
411 //
412 // Return the status.
413 //
414 return AM_HAL_STATUS_SUCCESS;
415 } // am_hal_ble_initialize()
416
417 //*****************************************************************************
418 //
419 // Initialize the global variables associated with a BLE module, and return its
420 // handle.
421 //
422 //*****************************************************************************
423 uint32_t
am_hal_ble_deinitialize(void * pHandle)424 am_hal_ble_deinitialize(void *pHandle)
425 {
426 am_hal_ble_state_t *pBLE = (am_hal_ble_state_t *)pHandle;
427
428 //
429 // Check the handle.
430 //
431 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
432 {
433 return AM_HAL_STATUS_INVALID_HANDLE;
434 }
435
436 //
437 // Initialize the handle.
438 //
439 memset(&(pBLE->sCurrentTransfer), 0, sizeof(am_hal_ble_transfer_t));
440
441 pBLE->prefix.s.bInit = false;
442 pBLE->prefix.s.magic = 0;
443 pBLE->ui32Module = 0;
444 pBLE->ui32TransferIndex = 0;
445 pBLE->bPatchComplete = 0;
446 pBLE->bContinuePacket = 0;
447 pBLE->bSavedPacket = 0;
448 pBLE->bBusy = 0;
449 pBLE->bCmdComplete = 0;
450 pBLE->bDmaComplete = 0;
451 pBLE->bFlowControlComplete = 0;
452
453 //
454 // Return the status.
455 //
456 return AM_HAL_STATUS_SUCCESS;
457 } // am_hal_ble_deinitialize()
458
459 //*****************************************************************************
460 //
461 // Configuration function.
462 //
463 //*****************************************************************************
464 uint32_t
am_hal_ble_config(void * pHandle,const am_hal_ble_config_t * psConfig)465 am_hal_ble_config(void *pHandle, const am_hal_ble_config_t *psConfig)
466 {
467 uint32_t ui32Module;
468 uint32_t ui32BleClkConfig;
469
470 //
471 // Check the handle.
472 //
473 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
474 {
475 return AM_HAL_STATUS_INVALID_HANDLE;
476 }
477
478 //
479 // Handle is good, so get the module number.
480 //
481 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
482
483 //
484 // Configure the SPI.
485 //
486 BLEIFn(ui32Module)->MSPICFG = 0x3;
487 BLEIFn(ui32Module)->MSPICFG_b.RDFC = 0;
488 BLEIFn(ui32Module)->MSPICFG_b.WTFC = 0;
489 BLEIFn(ui32Module)->MSPICFG_b.WTFCPOL = 1;
490 BLEIFn(ui32Module)->FIFOTHR_b.FIFOWTHR = psConfig->ui32WriteThreshold;
491 BLEIFn(ui32Module)->FIFOTHR_b.FIFORTHR = psConfig->ui32ReadThreshold;
492 BLEIFn(ui32Module)->FIFOCTRL |= BLEIF_FIFOCTRL_POPWR_Msk;
493
494 //
495 // Clock configuration register writes need to be combined to a single
496 // operation.
497 //
498 ui32BleClkConfig = _VAL2FLD(BLEIF_CLKCFG_FSEL, psConfig->ui32SpiClkCfg);
499 ui32BleClkConfig |= _VAL2FLD(BLEIF_CLKCFG_IOCLKEN, 1);
500
501 if (psConfig->ui32BleClockConfig == AM_HAL_BLE_CORE_MCU_CLK)
502 {
503 ui32BleClkConfig |= _VAL2FLD(BLEIF_CLKCFG_CLK32KEN, 1);
504 }
505
506 BLEIFn(ui32Module)->CLKCFG = ui32BleClkConfig;
507
508 if (APOLLO3_A1)
509 {
510 //
511 // Modify the BLE core's NVDS settings to match our configuration.
512 //
513 uint8_t *pui8NVDSData = (uint8_t *) am_ble_nvds_patch.pui32Data;
514
515 //
516 // Set the clock source.
517 //
518 pui8NVDSData[AM_HAL_BLE_NVDS_CLOCKSOURCE_OFFSET + 3] =
519 (psConfig->ui32BleClockConfig & 0xFF);
520
521 //
522 // Set the expected BLE clock drift PPM
523 //
524 pui8NVDSData[AM_HAL_BLE_NVDS_CLOCKDRIFT_OFFSET + 3] =
525 (psConfig->ui32ClockDrift & 0x00FF);
526
527 pui8NVDSData[AM_HAL_BLE_NVDS_CLOCKDRIFT_OFFSET + 4] =
528 (psConfig->ui32ClockDrift & 0xFF00) >> 8;
529
530 //
531 // Set the sleep clock drift PPM.
532 //
533 pui8NVDSData[AM_HAL_BLE_NVDS_SLEEPCLOCKDRIFT_OFFSET + 3] =
534 (psConfig->ui32SleepClockDrift & 0x00FF);
535
536 pui8NVDSData[AM_HAL_BLE_NVDS_SLEEPCLOCKDRIFT_OFFSET + 4] =
537 (psConfig->ui32SleepClockDrift & 0xFF00) >> 8;
538
539 //
540 // Configure Sleep mode.
541 //
542 pui8NVDSData[AM_HAL_BLE_NVDS_SLEEPENABLE_OFFSET + 3] = (psConfig->bSleepEnabled == true) ? 1 : 0;
543 //
544 // Configure AGC.
545 //
546 pui8NVDSData[AM_HAL_BLE_NVDS_AGC_OFFSET + 3] = (psConfig->bAgcEnabled == true) ? 1 : 0;
547
548 //
549 // Update the CRC.
550 //
551 am_ble_nvds_patch.ui32CRC = am_hal_ble_crc_nz(pui8NVDSData,
552 am_ble_nvds_patch.ui32Length);
553 }
554
555 //
556 // Save the addresses to the patches we intend to use.
557 //
558 g_sBLEState[ui32Module].bUseDefaultPatches = psConfig->bUseDefaultPatches;
559
560 //
561 // Return the status.
562 //
563 return AM_HAL_STATUS_SUCCESS;
564 } // am_hal_ble_config()
565
566 //*****************************************************************************
567 //
568 // Enable BLE
569 //
570 //*****************************************************************************
571 uint32_t
am_hal_ble_power_control(void * pHandle,uint32_t ui32PowerState)572 am_hal_ble_power_control(void *pHandle, uint32_t ui32PowerState)
573 {
574 uint32_t ui32Module;
575
576 //
577 // Check the handle.
578 //
579 if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
580 {
581 return AM_HAL_STATUS_INVALID_HANDLE;
582 }
583
584 //
585 // Handle is good, so get the module number.
586 //
587 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
588
589 if (ui32PowerState == AM_HAL_BLE_POWER_ACTIVE)
590 {
591 //
592 // Don't run this initialization if the BLE is already enabled.
593 //
594 if ( PWRCTRL->DEVPWRSTATUS_b.BLEL == 0)
595 {
596 MCUCTRL->FEATUREENABLE |= 1;
597 WHILE_TIMEOUT_MS ( ((MCUCTRL->FEATUREENABLE & 0x7) != 0x7), 100,
598 AM_HAL_BLE_FEATURE_DISABLED );
599
600 //
601 // Enable the BLE module.
602 //
603 if (am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_BLEL) !=
604 AM_HAL_STATUS_SUCCESS)
605 {
606 return AM_HAL_BLE_REGULATOR_FAILED;
607 }
608
609 //
610 // Release the BLE module RESET, start the "power state machine", and
611 // enable the clocks.
612 //
613 BLEIFn(ui32Module)->CLKCFG = _VAL2FLD(BLEIF_CLKCFG_CLK32KEN, 1);
614 BLEIFn(ui32Module)->BLEDBG_b.DBGDATA = 1 << 14;
615
616 //
617 // The reset bit is different between A0 and subsequent revisions.
618 //
619 if ( APOLLO3_GE_A1 )
620 {
621 MCUCTRL->MISCCTRL_b.BLE_RESETN = 1;
622 }
623 else
624 {
625 AM_REGVAL(0x40020198) = 0x1 << 2;
626 }
627
628 delay_ms(5);
629 BLEIFn(ui32Module)->BLECFG_b.PWRSMEN = 1;
630
631 //
632 // Wait for indication that the power is on.
633 //
634 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.PWRST != 3, 1000,
635 AM_HAL_BLE_POWERUP_INCOMPLETE );
636 }
637 }
638 else if (ui32PowerState == AM_HAL_BLE_POWER_OFF)
639 {
640 //
641 // Reverse of power-up. Disable clocks, set reset, then disable power.
642 //
643 BLEIFn(ui32Module)->CLKCFG = 0;
644 BLEIF->BLEDBG_b.DBGDATA = 0;
645
646 if ( APOLLO3_GE_A1 )
647 {
648 MCUCTRL->MISCCTRL_b.BLE_RESETN = 0;
649 }
650 else
651 {
652 AM_REGVAL(0x40020198) &= ~(0x1 << 2);
653 }
654
655 BLEIF->BLECFG_b.PWRSMEN = 0;
656
657 if (am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_BLEL) !=
658 AM_HAL_STATUS_SUCCESS)
659 {
660 return AM_HAL_BLE_SHUTDOWN_FAILED;
661 }
662
663 delay_us(100);
664 }
665 else
666 {
667 return AM_HAL_STATUS_INVALID_OPERATION;
668 }
669
670 //
671 // Return the status.
672 //
673 return AM_HAL_STATUS_SUCCESS;
674 } // am_hal_ble_power_control()
675
676 //************************************************************************
677 //
678 // Platform Reset function
679 //
680 //************************************************************************
681
682 static uint32_t
am_util_ble_platform_reset(void * pHandle)683 am_util_ble_platform_reset(void *pHandle)
684 {
685 am_hal_ble_buffer(16) sWriteCommand;
686 am_hal_ble_buffer(16) sResponse;
687 am_hal_ble_state_t *pBLE = pHandle;
688 uint32_t ui32IntEnable;
689
690 uint32_t ui32Module = pBLE->ui32Module;
691
692 // issue the HCI command with to reset hci
693 sWriteCommand.bytes[0] = 0x01;
694 sWriteCommand.bytes[1] = 0x11;
695 sWriteCommand.bytes[2] = 0xfc;
696 sWriteCommand.bytes[3] = 0x00;
697 //
698 // Temporarily disable BLE interrupts.
699 //
700 ui32IntEnable = BLEIFn(ui32Module)->INTEN;
701 BLEIFn(ui32Module)->INTEN = 0;
702
703 am_hal_ble_blocking_hci_write(pBLE,
704 AM_HAL_BLE_RAW,
705 sWriteCommand.words,
706 4);
707
708 BLEIFn(ui32Module)->BLEDBG_b.IOCLKON = 1;
709
710 //
711 // Wait for the response.
712 //
713 for (uint32_t i = 0; i < 1000; i++)
714 {
715 if ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ != 0 )
716 {
717 break;
718 }
719 else if (i == (1000 - 1))
720 {
721 return AM_HAL_BLE_NO_HCI_RESPONSE;
722 }
723 else
724 {
725 delay_ms(1);
726 }
727 }
728
729 am_hal_ble_blocking_hci_read(pBLE, sResponse.words, 0);
730
731 //
732 // Re-enable BLE interrupts.
733 //
734 BLEIFn(ui32Module)->INTCLR = ui32IntEnable;
735 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
736
737 return AM_HAL_STATUS_SUCCESS;
738 }
739
740
741 am_hal_ble_buffer(0x0064)am_ble_hw_patch_data =
742 {
743 .bytes =
744 {
745 0x00, 0x22, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0xdd, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x00, 0x00,
748
749 0x10, 0xbd, 0x00, 0x00, 0xcc, 0x6d, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, 0x01, 0x20, 0x80, 0xf3,
750 0x10, 0x88, 0x09, 0x48, 0x00, 0x78, 0x55, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x35, 0xfb, 0x07, 0x48,
751 0x40, 0x68, 0x04, 0x60, 0xE5, 0x20, 0x80, 0x47, 0xE5, 0x20, 0x80, 0x47, 0xE5, 0x20, 0x80, 0x47,
752 0xE5, 0x20, 0x80, 0x47, 0x10, 0xbd, 0x00, 0x00, 0x68, 0x68, 0x00, 0x20, 0x20, 0x68, 0x00, 0x20,
753 }
754 };
755
756 am_hal_ble_patch_t am_ble_hw_patch =
757 {
758 .ui32Type = 0xCC,
759 .ui32Length = 0x0064,
760 .ui32CRC = 0xc504,
761 .pui32Data = am_ble_hw_patch_data.words,
762 };
763
am_hal_ble_patch_preload(void * pHandle)764 uint32_t am_hal_ble_patch_preload(void *pHandle)
765 {
766 uint32_t *pRamCode = NULL;
767
768 if (APOLLO3_B0 || APOLLO3_GE_B0)
769 {
770 pRamCode = (uint32_t *) (am_ble_performance_patch_b0.pui32Data);
771 }
772 //don't download the patch here
773 //caculate the trim value and store in patch array.
774 am_hal_ble_default_trim_set_ramcode(pHandle);
775
776 am_hal_ble_patch_complete(pHandle);
777
778 am_hal_ble_plf_reg_write(pHandle, 0x43000004, 0xFFFFFFFF);
779 if (pRamCode)
780 {
781 am_hal_ble_plf_reg_write(pHandle, 0x43C00008, pRamCode[2]);
782 am_hal_ble_plf_reg_write(pHandle, 0x43C00000, pRamCode[3]);
783 }
784
785 //reset pmu registers
786 am_hal_ble_plf_reg_write(pHandle, 0x45800008, 0xa6a);
787 am_hal_ble_plf_reg_write(pHandle, 0x4580000c, 0x535);
788 am_hal_ble_plf_reg_write(pHandle, 0x45800010, 0xa6a);
789 am_hal_ble_plf_reg_write(pHandle, 0x45800014, 0x535);
790 am_hal_ble_plf_reg_write(pHandle, 0x45800018, 0x10A);
791 am_hal_ble_plf_reg_write(pHandle, 0x4580001c, 0x42);
792 am_hal_ble_plf_reg_write(pHandle, 0x45800020, 0x42);
793 am_hal_ble_plf_reg_write(pHandle, 0x45800024, 0x42);
794 am_hal_ble_plf_reg_write(pHandle, 0x45800028, 0x10A);
795 am_hal_ble_plf_reg_write(pHandle, 0x4580002c, 0x10A);
796 am_hal_ble_plf_reg_write(pHandle, 0x45800050, 0x60);
797 am_hal_ble_plf_reg_write(pHandle, 0x45800064, 0x4);
798 am_hal_ble_plf_reg_write(pHandle, 0x45800078, 0x60);
799 am_hal_ble_plf_reg_write(pHandle, 0x45800080, 0x60);
800 am_hal_ble_plf_reg_write(pHandle, 0x45800094, 0x021E);
801 am_hal_ble_plf_reg_write(pHandle, 0x458000a0, 0x20);
802
803 //download a hardware patch for performing a softreset
804 for (uint32_t i = 0; i < 25; i++)
805 {
806 am_hal_ble_plf_reg_write(pHandle, 0x20003E9C + i * 4, am_ble_hw_patch.pui32Data[i]);
807 }
808
809 am_hal_ble_plf_reg_write(pHandle, 0x51C00018, am_ble_hw_patch.pui32Data[2]);
810 am_hal_ble_plf_reg_write(pHandle, 0x51C00014, am_ble_hw_patch.pui32Data[1]);
811 delay_ms(50);
812 am_util_ble_platform_reset(pHandle);
813 delay_ms(50);
814 am_hal_ble_state_t *pBLE1 = (am_hal_ble_state_t *)pHandle;
815 pBLE1->bPatchComplete = 0;
816 return AM_HAL_STATUS_SUCCESS;
817 }
818
819
820 //*****************************************************************************
821 //
822 // Perform all of the operations necessary to prepare the BLE controller for
823 // HCI operation.
824 //
825 //*****************************************************************************
826 uint32_t
am_hal_ble_boot(void * pHandle)827 am_hal_ble_boot(void *pHandle)
828 {
829 uint32_t ui32Status;
830
831 //
832 // Check the handle.
833 //
834 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
835 {
836 return AM_HAL_STATUS_INVALID_HANDLE;
837 }
838
839 //
840 // The handle is good, so we can access it as a structure.
841 //
842 am_hal_ble_state_t *pBLE = pHandle;
843
844 if (pBLE->bUseDefaultPatches)
845 {
846 //
847 // The B0 silicon patching method is slightly different from A1. B0 silicon
848 // does not require the Copy Patch method introduced for A1 silicon.
849 //
850 if (APOLLO3_A0 || APOLLO3_A1)
851 {
852 ui32Status = am_hal_ble_default_copy_patch_apply(pHandle);
853 if (ui32Status != AM_HAL_STATUS_SUCCESS)
854 {
855 return ui32Status;
856 }
857 }
858
859 // B0 silicon patch load
860 if (APOLLO3_B0 || APOLLO3_GE_B0)
861 {
862 ui32Status = am_hal_ble_patch_preload(pHandle);
863 if (ui32Status != AM_HAL_STATUS_SUCCESS)
864 {
865 return ui32Status;
866 }
867 }
868
869 //
870 // Apply the BLE trim value
871 //
872 ui32Status = am_hal_ble_default_trim_set_ramcode(pHandle);
873 if (ui32Status != AM_HAL_STATUS_SUCCESS)
874 {
875 return ui32Status;
876 }
877
878 //
879 // Apply the NVDS patch.
880 //
881 ui32Status = am_hal_ble_default_patch_apply(pHandle);
882 if (ui32Status != AM_HAL_STATUS_SUCCESS)
883 {
884 return ui32Status;
885 }
886
887 //
888 // Complete the patching step
889 //
890 ui32Status = am_hal_ble_patch_complete(pHandle);
891 if (ui32Status != AM_HAL_STATUS_SUCCESS)
892 {
893 return ui32Status;
894 }
895 }
896
897 if (am_hal_ble_check_32k_clock(pBLE) == AM_HAL_STATUS_FAIL)
898 {
899 return AM_HAL_BLE_32K_CLOCK_UNSTABLE;
900 }
901 else
902 {
903 return AM_HAL_STATUS_SUCCESS;
904 }
905 } // am_hal_ble_boot()
906
907 //*****************************************************************************
908 //
909 // Apply a patch.
910 //
911 // Returns 0 for success or a numerical error code for failures.
912 //
913 //*****************************************************************************
914 uint32_t
am_hal_ble_patch_apply(void * pHandle,am_hal_ble_patch_t * psPatch)915 am_hal_ble_patch_apply(void *pHandle, am_hal_ble_patch_t *psPatch)
916 {
917 uint8_t pui8ExpectedResponse[32];
918 uint32_t ui32ErrorStatus;
919 uint32_t ui32Trial;
920
921 //
922 // Check the handle.
923 //
924 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
925 {
926 return AM_HAL_STATUS_INVALID_HANDLE;
927 }
928
929 uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
930 am_hal_ble_transfer_t sTransfer;
931 am_hal_ble_buffer(16) psPatchBuffer;
932
933 //
934 // Send a header packet.
935 //
936 psPatchBuffer.bytes[0] = 0x01;
937 psPatchBuffer.bytes[1] = psPatch->ui32Type;
938 psPatchBuffer.bytes[2] = 0xF1;
939 psPatchBuffer.bytes[3] = 0x02;
940 psPatchBuffer.bytes[4] = (psPatch->ui32Length & 0xFF);
941 psPatchBuffer.bytes[5] = ((psPatch->ui32Length >> 8) & 0xFF);
942
943 //
944 // This first packet might take a few tries.
945 //
946 for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_TRIALS; ui32Trial++)
947 {
948 ui32ErrorStatus = am_hal_ble_blocking_hci_write(pHandle,
949 AM_HAL_BLE_RAW,
950 psPatchBuffer.words,
951 6);
952
953 if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
954 {
955 break;
956 }
957 }
958
959 if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
960 {
961 return ui32ErrorStatus;
962 }
963
964 //
965 // Wait for the header response. It should be 5 bytes long.
966 //
967 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000,
968 AM_HAL_BLE_NO_HCI_RESPONSE );
969
970 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
971 sTransfer.ui8Command = AM_HAL_BLE_READ;
972 sTransfer.pui32Data = psPatchBuffer.words;
973 sTransfer.ui16Length = 5;
974
975 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
976 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
977 {
978 return ui32ErrorStatus;
979 }
980
981 pui8ExpectedResponse[0] = 0x04;
982 pui8ExpectedResponse[1] = psPatch->ui32Type;
983 pui8ExpectedResponse[2] = 0xF1;
984 pui8ExpectedResponse[3] = 0x01;
985 pui8ExpectedResponse[4] = 0x00;
986
987 if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
988 {
989 return AM_HAL_STATUS_FAIL;
990 }
991
992 //
993 // Send all of the data, including the acknowledgements.
994 //
995 uint32_t ui32RemainingBytes = psPatch->ui32Length;
996 uint32_t ui32Index = 0;
997
998 while (ui32RemainingBytes)
999 {
1000 //
1001 // Figure out how many bytes to send in the next packet.
1002 //
1003 uint32_t ui32TransferSize = (ui32RemainingBytes > MAX_PATCH_PACKET_LEN ?
1004 MAX_PATCH_PACKET_LEN : ui32RemainingBytes);
1005
1006 //
1007 // Send a data header.
1008 //
1009 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1010 sTransfer.ui8Command = AM_HAL_BLE_WRITE;
1011 sTransfer.pui32Data = g_psPatchBuffer.words;
1012 sTransfer.ui16Length = ui32TransferSize + 4;
1013 sTransfer.bContinue = false;
1014
1015 g_psPatchBuffer.bytes[0] = 0x01;
1016 g_psPatchBuffer.bytes[1] = psPatch->ui32Type;
1017 g_psPatchBuffer.bytes[2] = 0xF2;
1018 g_psPatchBuffer.bytes[3] = ui32TransferSize;
1019
1020 // copy data into buffer
1021 memcpy(&g_psPatchBuffer.bytes[4], (uint8_t *)&(psPatch->pui32Data[ui32Index / 4]), ui32TransferSize);
1022
1023 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1024 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1025 {
1026 return ui32ErrorStatus;
1027 }
1028
1029 //
1030 // Read the acknowledgement.
1031 //
1032 WHILE_TIMEOUT_MS( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000,
1033 AM_HAL_BLE_NO_HCI_RESPONSE);
1034
1035 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1036 sTransfer.ui8Command = AM_HAL_BLE_READ;
1037 sTransfer.pui32Data = psPatchBuffer.words;
1038 sTransfer.ui16Length = 5;
1039
1040 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1041 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1042 {
1043 return ui32ErrorStatus;
1044 }
1045
1046 pui8ExpectedResponse[0] = 0x04;
1047 pui8ExpectedResponse[1] = psPatch->ui32Type;
1048 pui8ExpectedResponse[2] = 0xF2;
1049 pui8ExpectedResponse[3] = 0x01;
1050 pui8ExpectedResponse[4] = 0x00;
1051
1052 if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
1053 {
1054 return AM_HAL_STATUS_FAIL;
1055 }
1056
1057 //
1058 // Update the tracking variables
1059 //
1060 ui32RemainingBytes -= ui32TransferSize;
1061 ui32Index += ui32TransferSize;
1062 }
1063
1064 //
1065 // Send the CRC, and make sure we got it right.
1066 //
1067 psPatchBuffer.bytes[0] = 0x01;
1068 psPatchBuffer.bytes[1] = psPatch->ui32Type;
1069 psPatchBuffer.bytes[2] = 0xF3;
1070 psPatchBuffer.bytes[3] = 0x02;
1071 psPatchBuffer.bytes[4] = (psPatch->ui32CRC & 0xFF);
1072 psPatchBuffer.bytes[5] = ((psPatch->ui32CRC >> 8) & 0xFF);
1073
1074 if (am_hal_ble_blocking_hci_write(pHandle, AM_HAL_BLE_RAW, psPatchBuffer.words, 6) !=
1075 AM_HAL_STATUS_SUCCESS)
1076 {
1077 return AM_HAL_STATUS_FAIL;
1078 }
1079
1080 //
1081 // Wait for the header response. It should be 5 bytes long.
1082 //
1083 WHILE_TIMEOUT_MS( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000,
1084 AM_HAL_BLE_NO_HCI_RESPONSE );
1085
1086 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1087 sTransfer.ui8Command = AM_HAL_BLE_READ;
1088 sTransfer.pui32Data = psPatchBuffer.words;
1089 sTransfer.ui16Length = 5;
1090
1091 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1092 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1093 {
1094 return ui32ErrorStatus;
1095 }
1096
1097 pui8ExpectedResponse[0] = 0x04;
1098 pui8ExpectedResponse[1] = psPatch->ui32Type;
1099 pui8ExpectedResponse[2] = 0xF3;
1100 pui8ExpectedResponse[3] = 0x01;
1101 pui8ExpectedResponse[4] = 0x00;
1102
1103 if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
1104 {
1105 return AM_HAL_STATUS_FAIL;
1106 }
1107 else
1108 {
1109 return AM_HAL_STATUS_SUCCESS;
1110 }
1111 } // am_hal_ble_patch_apply()
1112
1113 //*****************************************************************************
1114 // @brief
1115 //
1116 // @param pHandle
1117 // @return uint32_t
1118 //*****************************************************************************
1119
1120 uint32_t
am_hal_ble_patch_copy_end_apply(void * pHandle)1121 am_hal_ble_patch_copy_end_apply(void *pHandle)
1122 {
1123 uint8_t pui8ExpectedResponse[32];
1124 uint32_t ui32ErrorStatus;
1125 uint32_t ui32Trial;
1126
1127 //
1128 // Check the handle.
1129 //
1130 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1131 {
1132 return AM_HAL_STATUS_INVALID_HANDLE;
1133 }
1134
1135 uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
1136 am_hal_ble_transfer_t sTransfer;
1137 am_hal_ble_buffer(16) psPatchBuffer;
1138
1139 //
1140 // Send a header packet.
1141 //
1142 psPatchBuffer.bytes[0] = 0x01;
1143 psPatchBuffer.bytes[1] = 0xEE;
1144 psPatchBuffer.bytes[2] = 0xF1;
1145 psPatchBuffer.bytes[3] = 0x02;
1146 psPatchBuffer.bytes[4] = 0x00;
1147 psPatchBuffer.bytes[5] = 0x00;
1148
1149 //
1150 // This first packet might take a few tries.
1151 //
1152 for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_TRIALS; ui32Trial++)
1153 {
1154 ui32ErrorStatus = am_hal_ble_blocking_hci_write(pHandle,
1155 AM_HAL_BLE_RAW,
1156 psPatchBuffer.words,
1157 6);
1158
1159 if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
1160 {
1161
1162 break;
1163 }
1164 }
1165
1166 if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1167 {
1168
1169 return ui32ErrorStatus;
1170 }
1171
1172 //
1173 // Wait for the header response. It should be 5 bytes long.
1174 //
1175 WHILE_TIMEOUT_MS( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000, AM_HAL_BLE_NO_HCI_RESPONSE);
1176
1177 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1178 sTransfer.ui8Command = AM_HAL_BLE_READ;
1179 sTransfer.pui32Data = psPatchBuffer.words;
1180 sTransfer.ui16Length = 5;
1181
1182 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1183 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1184 {
1185
1186 return ui32ErrorStatus;
1187 }
1188
1189 pui8ExpectedResponse[0] = 0x04;
1190 pui8ExpectedResponse[1] = 0xEE;
1191 pui8ExpectedResponse[2] = 0xF1;
1192 pui8ExpectedResponse[3] = 0x01;
1193 pui8ExpectedResponse[4] = 0x00;
1194
1195 if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
1196 {
1197
1198 return AM_HAL_STATUS_FAIL;
1199 }
1200 return 0;
1201 } // am_hal_ble_patch_copy_end_apply()
1202
1203 //*****************************************************************************
1204 //
1205 // Apply the default copy patch.
1206 //
1207 // Returns 0 for success or a numerical error code for failures.
1208 //
1209 //*****************************************************************************
1210 uint32_t
am_hal_ble_default_copy_patch_apply(void * pHandle)1211 am_hal_ble_default_copy_patch_apply(void *pHandle)
1212 {
1213 uint32_t ui32Status;
1214 uint16_t ui16Crc;
1215
1216 am_hal_ble_patch_t **psCopyPatch;
1217
1218 psCopyPatch = am_hal_ble_default_copy_patches;
1219
1220 ui16Crc = am_hal_ble_crc_nz((uint8_t*)(psCopyPatch[0]->pui32Data), psCopyPatch[0]->ui32Length);
1221 psCopyPatch[0]->ui32CRC = ui16Crc;
1222 ui32Status = am_hal_ble_patch_apply(pHandle, psCopyPatch[0]);
1223 if (ui32Status != AM_HAL_STATUS_SUCCESS)
1224 {
1225 return ui32Status;
1226 }
1227
1228 ui32Status = am_hal_ble_patch_copy_end_apply(pHandle);
1229 if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1230 {
1231 return ui32Status;
1232 }
1233
1234 return AM_HAL_STATUS_SUCCESS;
1235 }
1236
1237 //*****************************************************************************
1238 //
1239 // Apply the default patch.
1240 //
1241 // Returns 0 for success or a numerical error code for failures.
1242 //
1243 //*****************************************************************************
1244 uint32_t
am_hal_ble_default_patch_apply(void * pHandle)1245 am_hal_ble_default_patch_apply(void *pHandle)
1246 {
1247 uint32_t ui32Status, i = 0;
1248 uint16_t ui16Crc;
1249 uint32_t ui32NumPatches;
1250 am_hal_ble_patch_t **psDefaultPatches;
1251
1252 if (APOLLO3_A0 || APOLLO3_A1)
1253 {
1254 ui32NumPatches = am_hal_ble_num_default_patches;
1255 psDefaultPatches = am_hal_ble_default_patches;
1256 }
1257 else if (APOLLO3_B0)
1258 {
1259 ui32NumPatches = am_hal_ble_num_default_patches_b0;
1260 psDefaultPatches = am_hal_ble_default_patches_b0;
1261 }
1262 else
1263 {
1264 return AM_HAL_STATUS_FAIL;
1265 }
1266
1267 for ( i = 0; i < ui32NumPatches; i++ )
1268 {
1269 ui16Crc = am_hal_ble_crc_nz((uint8_t*)(psDefaultPatches[i]->pui32Data), psDefaultPatches[i]->ui32Length);
1270 psDefaultPatches[i]->ui32CRC = ui16Crc;
1271 ui32Status = am_hal_ble_patch_apply(pHandle, psDefaultPatches[i]);
1272 if (ui32Status != AM_HAL_STATUS_SUCCESS)
1273 {
1274 return ui32Status;
1275 }
1276 }
1277
1278 return AM_HAL_STATUS_SUCCESS;
1279 } // am_hal_ble_default_patch_apply()
1280
1281 //*****************************************************************************
1282 //
1283 // Complete the patching process
1284 //
1285 //*****************************************************************************
1286 uint32_t
am_hal_ble_patch_complete(void * pHandle)1287 am_hal_ble_patch_complete(void *pHandle)
1288 {
1289 uint32_t ui32ErrorStatus;
1290 am_hal_ble_transfer_t sTransfer;
1291 am_hal_ble_buffer(12) sTxBuffer;
1292 am_hal_ble_buffer(12) sRxBuffer;
1293 uint32_t ui32Trial;
1294
1295 am_hal_ble_state_t *pBLE = pHandle;
1296
1297 //
1298 // Check the handle.
1299 //
1300 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1301 {
1302 return AM_HAL_STATUS_INVALID_HANDLE;
1303 }
1304
1305 uint32_t ui32Module = pBLE->ui32Module;
1306
1307 //
1308 // Write the "patch complete" command.
1309 //
1310 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1311 sTransfer.ui8Command = AM_HAL_BLE_WRITE;
1312 sTransfer.pui32Data = sTxBuffer.words;
1313 sTransfer.ui16Length = 6;
1314
1315 sTxBuffer.bytes[0] = 0x01;
1316 sTxBuffer.bytes[1] = 0xEE;
1317 sTxBuffer.bytes[2] = 0xF1;
1318 sTxBuffer.bytes[3] = 0x02;
1319 sTxBuffer.bytes[4] = 0x00;
1320 sTxBuffer.bytes[5] = 0x00;
1321
1322 for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_CMP_TRIALS; ui32Trial++)
1323 {
1324 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1325 if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
1326 {
1327 break;
1328 }
1329 }
1330
1331 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 100,
1332 AM_HAL_BLE_NO_HCI_RESPONSE );
1333
1334 //
1335 // Read back the response.
1336 //
1337 sTransfer.ui8Command = AM_HAL_BLE_READ;
1338 sTransfer.pui32Data = sRxBuffer.words;
1339 sTransfer.ui16Length = 2;
1340 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1341 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1342 {
1343 return ui32ErrorStatus;
1344 }
1345
1346 //
1347 // Check to see which format the response came back in. If it doesn't have
1348 // a 2-byte length header, we need to manually override the length, and
1349 // continue on to adjust the HCI format in the next packet. Otherwise, we
1350 // can just return from here.
1351 //
1352 if ( sRxBuffer.bytes[1] == 0xEE )
1353 {
1354 sTransfer.ui16Length = 3;
1355 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1356 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1357 {
1358 return ui32ErrorStatus;
1359 }
1360 }
1361 else
1362 {
1363 sTransfer.ui16Length = (sRxBuffer.bytes[0] + (sRxBuffer.bytes[1] << 8));
1364 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1365 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1366 {
1367 return ui32ErrorStatus;
1368 }
1369
1370 //
1371 // Make sure to remember that we've sent the "patch complete" packet.
1372 //
1373 pBLE->bPatchComplete = true;
1374
1375 return AM_HAL_STATUS_SUCCESS;
1376 }
1377
1378 //
1379 // If we made it here, we need to tell the radio that we need two-byte
1380 // headers prepended to each HCI packet it sends us.
1381 //
1382 memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1383 sTransfer.ui8Command = AM_HAL_BLE_WRITE;
1384 sTransfer.pui32Data = sTxBuffer.words;
1385 sTransfer.ui16Length = 5;
1386
1387 sTxBuffer.bytes[0] = 0x01;
1388 sTxBuffer.bytes[1] = 0x04;
1389 sTxBuffer.bytes[2] = 0xFD;
1390 sTxBuffer.bytes[3] = 0x01;
1391 sTxBuffer.bytes[4] = 0x01;
1392
1393 for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_CMP_TRIALS; ui32Trial++)
1394 {
1395 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1396 if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
1397 {
1398 break;
1399 }
1400 }
1401
1402 if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1403 {
1404 return ui32ErrorStatus;
1405 }
1406
1407 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 100,
1408 AM_HAL_BLE_NO_HCI_RESPONSE );
1409
1410 sTransfer.ui8Command = AM_HAL_BLE_READ;
1411 sTransfer.pui32Data = sRxBuffer.words;
1412 sTransfer.ui16Length = 9;
1413 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1414 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1415 {
1416 return ui32ErrorStatus;
1417 }
1418
1419 //
1420 // Now that we're done patching, we can let the radio sleep.
1421 //
1422 am_hal_ble_wakeup_set(pBLE, 0);
1423
1424 //
1425 // Make sure to remember that we've sent the "patch complete" packet.
1426 //
1427 pBLE->bPatchComplete = true;
1428
1429 //
1430 // Delay to give the BLE core time to take the patch (assuming a patch was sent).
1431 //
1432 delay_ms(500);
1433
1434 //
1435 // Load the modex trim data to the BLE controller.
1436 //
1437 am_hal_ble_load_modex_trim_set(pBLE);
1438
1439 //
1440 // Return the status.
1441 //
1442 return AM_HAL_STATUS_SUCCESS;
1443 } // am_hal_ble_patch_complete()
1444
1445 //*****************************************************************************
1446 //
1447 // Set one of the trim values for the BLE core.
1448 //
1449 //*****************************************************************************
1450 uint32_t
am_hal_ble_trim_set(void * pHandle,uint32_t ui32BleCoreAddress,uint32_t ui32TrimValue,uint32_t ui32TrimMask)1451 am_hal_ble_trim_set(void *pHandle, uint32_t ui32BleCoreAddress, uint32_t ui32TrimValue, uint32_t ui32TrimMask)
1452 {
1453 am_hal_ble_state_t *pBLE = pHandle;
1454 uint32_t ui32TrimValueSwapped, ui32LockValue, ui32ReadVal, ui32WriteVal;
1455
1456 ui32TrimValueSwapped = (((ui32TrimValue & 0x000000FF) << 24) |
1457 ((ui32TrimValue & 0x0000FF00) << 8) |
1458 ((ui32TrimValue & 0x00FF0000) >> 8) |
1459 ((ui32TrimValue & 0xFF000000) >> 24));
1460
1461 if (ui32TrimValue != 0xFFFFFFFF)
1462 {
1463 //
1464 // Unlock the BLE registers and save the "lock register" value.
1465 //
1466 am_hal_ble_plf_reg_read(pBLE, 0x43000004, &ui32LockValue);
1467 am_hal_ble_plf_reg_write(pBLE, 0x43000004, 0xFFFFFFFF);
1468
1469 //
1470 // Check to see if we need a bitfield mask. If not, we can just write
1471 // directly.
1472 //
1473 if (ui32TrimMask == 0xFFFFFFFF)
1474 {
1475 am_hal_ble_plf_reg_write(pBLE, ui32BleCoreAddress, ui32TrimValueSwapped);
1476 }
1477 else
1478 {
1479 //
1480 // If we do need a mask, read the register, mask out the old bits,
1481 // OR in the new, and write the new value back.
1482 //
1483 am_hal_ble_plf_reg_read(pBLE, ui32BleCoreAddress, &ui32ReadVal);
1484 ui32WriteVal = ((ui32ReadVal & (~ui32TrimMask)) | ui32TrimValueSwapped);
1485
1486 am_hal_ble_plf_reg_write(pBLE, ui32BleCoreAddress, ui32WriteVal);
1487 }
1488
1489 //
1490 // Unlock the BLE register.
1491 //
1492 am_hal_ble_plf_reg_write(pBLE, 0x43000004, ui32LockValue);
1493 }
1494
1495 return AM_HAL_STATUS_SUCCESS;
1496 } // am_hal_ble_trim_set()
1497
1498 //*****************************************************************************
1499 //
1500 // Set the bandgap voltage, bandgap current, and retention LDO output values
1501 // based on the tested values stored in non-volatile memory.
1502 //
1503 //*****************************************************************************
1504 uint32_t
am_hal_ble_default_trim_set_ramcode(void * pHandle)1505 am_hal_ble_default_trim_set_ramcode(void *pHandle)
1506 {
1507 uint32_t ui32TrimValue;
1508 uint32_t ui32TrimValueSwapped;
1509 uint32_t *pRamCode;
1510
1511 if (APOLLO3_B0)
1512 {
1513 pRamCode = (uint32_t *) (am_ble_performance_patch_b0.pui32Data);
1514 }
1515 else
1516 {
1517 pRamCode = (uint32_t *) (am_ble_performance_patch.pui32Data);
1518 }
1519
1520 //
1521 // Set the bandgap voltage and current.
1522 //
1523 //ui32TrimValue = (AM_REGVAL(0x50023800) | (0x0F000000)) & (0xEFFFFFFF);
1524 ui32TrimValue = AM_REGVAL(0x50023800);
1525 ui32TrimValueSwapped = (((ui32TrimValue & 0x000000FF) << 24) |
1526 ((ui32TrimValue & 0x0000FF00) << 8) |
1527 ((ui32TrimValue & 0x00FF0000) >> 8) |
1528 ((ui32TrimValue & 0xFF000000) >> 24));
1529
1530 if (ui32TrimValueSwapped != 0xFFFFFFFF)
1531 {
1532 pRamCode[2] = ui32TrimValueSwapped;
1533 }
1534
1535 //
1536 // Set the retention LDO voltage.
1537 //
1538 ui32TrimValue = AM_REGVAL(0x50023804);
1539 if (ui32TrimValue != 0xFFFFFFFF)
1540 {
1541 // 0xFFFFFFFF means the part has not been trimed.
1542 ui32TrimValue += 0x40000000; // Increase the retention voltage to > 0.75v
1543 }
1544 ui32TrimValueSwapped = (((ui32TrimValue & 0x000000FF) << 24) |
1545 ((ui32TrimValue & 0x0000FF00) << 8) |
1546 ((ui32TrimValue & 0x00FF0000) >> 8) |
1547 ((ui32TrimValue & 0xFF000000) >> 24));
1548
1549 if ( ui32TrimValueSwapped != 0xFFFFFFFF )
1550 {
1551 pRamCode[3] = ((pRamCode[3] & (~0x1F0)) | ui32TrimValueSwapped);
1552 }
1553
1554 return AM_HAL_STATUS_SUCCESS;
1555 } // am_hal_ble_default_trim_set_ramcode()
1556
1557 //*****************************************************************************
1558 //
1559 // Builds a vendor-specific BLE command.
1560 //
1561 //*****************************************************************************
1562 uint32_t
am_hal_ble_vs_command_build(uint32_t * pui32Command,uint32_t ui32OpCode,uint32_t ui32TotalLength,uint8_t * pui8Parameters)1563 am_hal_ble_vs_command_build(uint32_t *pui32Command, uint32_t ui32OpCode,
1564 uint32_t ui32TotalLength, uint8_t *pui8Parameters)
1565 {
1566 uint8_t *pui8Dest = (uint8_t *) pui32Command;
1567
1568 //
1569 // Build the header portion of the command from the given argments.
1570 //
1571 pui8Dest[0] = 0x01;
1572 pui8Dest[1] = ui32OpCode & 0xFF;
1573 pui8Dest[2] = (ui32OpCode >> 8) & 0xFF;
1574 pui8Dest[3] = (ui32TotalLength - 4) & 0xFF;
1575
1576 //
1577 // Finish filling the array with any parameters that may be required.
1578 //
1579 for (uint32_t i = 4; i < ui32TotalLength; i++)
1580 {
1581 pui8Dest[i] = pui8Parameters[i - 4];
1582 }
1583
1584 //
1585 // Return the status.
1586 //
1587 return AM_HAL_STATUS_SUCCESS;
1588 } // am_hal_ble_vs_command_build()
1589
1590 //*****************************************************************************
1591 //
1592 // Returns the number of bytes written.
1593 //
1594 //*****************************************************************************
1595 uint32_t
am_hal_ble_blocking_hci_write(void * pHandle,uint8_t ui8Type,uint32_t * pui32Data,uint32_t ui32NumBytes)1596 am_hal_ble_blocking_hci_write(void *pHandle, uint8_t ui8Type,
1597 uint32_t *pui32Data, uint32_t ui32NumBytes)
1598 {
1599 uint32_t ui32ErrorStatus;
1600
1601 am_hal_ble_transfer_t HciWrite =
1602 {
1603 .pui32Data = pui32Data,
1604 .pui8Offset = {ui8Type, 0x0, 0x0},
1605 .ui8OffsetLen = 0,
1606 .ui16Length = ui32NumBytes,
1607 .ui8Command = AM_HAL_BLE_WRITE,
1608 .ui8RepeatCount = 0,
1609 .bContinue = false,
1610 .pfnTransferCompleteCB = 0x0,
1611 .pvContext = 0x0,
1612 };
1613
1614 //
1615 // Check the handle.
1616 //
1617 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1618 {
1619 return 0;
1620 }
1621
1622 //
1623 // Fix up the offset length based on the packet type, and send the bytes.
1624 //
1625 if (ui8Type != AM_HAL_BLE_RAW)
1626 {
1627 HciWrite.ui8OffsetLen = 1;
1628 }
1629
1630 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &HciWrite);
1631 if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1632 {
1633 return ui32ErrorStatus;
1634 }
1635
1636 return AM_HAL_STATUS_SUCCESS;
1637 } // am_hal_ble_blocking_hci_write()
1638
1639 //*****************************************************************************
1640 //
1641 // Returns the number of bytes received.
1642 //
1643 //*****************************************************************************
1644 uint32_t
am_hal_ble_blocking_hci_read(void * pHandle,uint32_t * pui32Data,uint32_t * pui32BytesReceived)1645 am_hal_ble_blocking_hci_read(void *pHandle, uint32_t *pui32Data, uint32_t *pui32BytesReceived)
1646 {
1647 uint32_t ui32Module, ui32NumBytes, ui32ErrorStatus;
1648
1649 am_hal_ble_buffer(2) sLengthBytes;
1650
1651 am_hal_ble_transfer_t HciRead =
1652 {
1653 .pui32Data = sLengthBytes.words,
1654 .pui8Offset = {0x0, 0x0, 0x0},
1655 .ui8OffsetLen = 0,
1656 .ui16Length = 2,
1657 .ui8Command = AM_HAL_BLE_READ,
1658 .ui8RepeatCount = 0,
1659 .bContinue = false,
1660 .pfnTransferCompleteCB = 0x0,
1661 .pvContext = 0x0,
1662 };
1663
1664 //
1665 // Check the handle.
1666 //
1667 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1668 {
1669 return 0;
1670 }
1671
1672 //
1673 // Handle is good, so get the module number.
1674 //
1675 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
1676
1677 //
1678 // Make sure the IRQ signal is set.
1679 //
1680 if ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ )
1681 {
1682 //
1683 // Read the length bytes.
1684 //
1685 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &HciRead);
1686 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1687 {
1688 return ui32ErrorStatus;
1689 }
1690
1691 //
1692 // Read the rest of the packet.
1693 //
1694 HciRead.pui32Data = pui32Data;
1695 HciRead.ui16Length = (sLengthBytes.bytes[0] +
1696 (sLengthBytes.bytes[1] << 8));
1697
1698 //
1699 // Check if the length is not out of the boundary
1700 //
1701 if ( (HciRead.ui16Length == 0) || (HciRead.ui16Length > 256) )
1702 {
1703 return AM_HAL_STATUS_OUT_OF_RANGE;
1704 }
1705
1706 ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &HciRead);
1707 if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1708 {
1709 return ui32ErrorStatus;
1710 }
1711
1712 ui32NumBytes = HciRead.ui16Length;
1713 }
1714 else
1715 {
1716 ui32NumBytes = 0;
1717 }
1718
1719 if (pui32BytesReceived)
1720 {
1721 *pui32BytesReceived = ui32NumBytes;
1722 }
1723
1724 return AM_HAL_STATUS_SUCCESS;
1725 } // am_hal_ble_blocking_hci_read()
1726
1727 //*****************************************************************************
1728 //
1729 // Returns the number of bytes written.
1730 //
1731 //*****************************************************************************
1732 uint32_t
am_hal_ble_nonblocking_hci_write(void * pHandle,uint8_t ui8Type,uint32_t * pui32Data,uint32_t ui32NumBytes,am_hal_ble_transfer_complete_cb_t pfnCallback,void * pvContext)1733 am_hal_ble_nonblocking_hci_write(void *pHandle, uint8_t ui8Type,
1734 uint32_t *pui32Data, uint32_t ui32NumBytes,
1735 am_hal_ble_transfer_complete_cb_t pfnCallback,
1736 void *pvContext)
1737 {
1738 //
1739 // Check the handle.
1740 //
1741 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1742 {
1743 return 0;
1744 }
1745
1746 am_hal_ble_transfer_t HciWrite =
1747 {
1748 .pui32Data = pui32Data,
1749 .pui8Offset = {ui8Type, 0x0, 0x0},
1750 .ui8OffsetLen = 0,
1751 .ui16Length = ui32NumBytes,
1752 .ui8Command = AM_HAL_BLE_WRITE,
1753 .ui8RepeatCount = 0,
1754 .bContinue = false,
1755 .pfnTransferCompleteCB = pfnCallback,
1756 .pvContext = pvContext,
1757 };
1758
1759 //
1760 // Fix up the offset length based on the packet type, and send the bytes.
1761 //
1762 if (ui8Type != AM_HAL_BLE_RAW)
1763 {
1764 HciWrite.ui8OffsetLen = 1;
1765 }
1766
1767 uint32_t ui32Status = am_hal_ble_nonblocking_transfer(pHandle, &HciWrite);
1768
1769 return ui32Status;
1770 } // am_hal_ble_nonblocking_hci_write()
1771
1772 //*****************************************************************************
1773 //
1774 // Returns the number of bytes received.
1775 //
1776 //*****************************************************************************
1777 uint32_t
am_hal_ble_nonblocking_hci_read(void * pHandle,uint32_t * pui32Data,am_hal_ble_transfer_complete_cb_t pfnCallback,void * pvContext)1778 am_hal_ble_nonblocking_hci_read(void *pHandle, uint32_t *pui32Data,
1779 am_hal_ble_transfer_complete_cb_t pfnCallback,
1780 void *pvContext)
1781 {
1782 uint32_t ui32Status;
1783 am_hal_ble_state_t *pBle = pHandle;
1784
1785 am_hal_ble_buffer(2) sLengthBytes;
1786
1787 am_hal_ble_transfer_t HciRead =
1788 {
1789 .pui32Data = sLengthBytes.words,
1790 .pui8Offset = {0x0, 0x0, 0x0},
1791 .ui8OffsetLen = 0,
1792 .ui16Length = 2,
1793 .ui8Command = AM_HAL_BLE_READ,
1794 .ui8RepeatCount = 0,
1795 .bContinue = false,
1796 .pfnTransferCompleteCB = pfnCallback,
1797 .pvContext = pvContext,
1798 };
1799
1800 //
1801 // Check the handle.
1802 //
1803 if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
1804 {
1805 return AM_HAL_STATUS_INVALID_HANDLE;
1806 }
1807
1808 //
1809 // Make sure the IRQ signal is set.
1810 //
1811 if ( am_hal_ble_check_irq(pBle) )
1812 {
1813 //
1814 // Read the length bytes.
1815 //
1816 ui32Status = am_hal_ble_blocking_transfer(pHandle, &HciRead);
1817
1818 if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1819 {
1820 return ui32Status;
1821 }
1822
1823 //
1824 // Read the rest of the packet.
1825 //
1826 HciRead.pfnTransferCompleteCB = pfnCallback;
1827 HciRead.pui32Data = pui32Data;
1828 HciRead.ui16Length = (sLengthBytes.bytes[0] +
1829 (sLengthBytes.bytes[1] << 8));
1830
1831 return am_hal_ble_nonblocking_transfer(pHandle, &HciRead);
1832 }
1833
1834 //
1835 // If we get here, return fail.
1836 //
1837 return AM_HAL_STATUS_FAIL;
1838 } // am_hal_ble_nonblocking_hci_read()
1839
1840 //*****************************************************************************
1841 //
1842 // Return true if BSTATUS is high.
1843 //
1844 //*****************************************************************************
1845 static bool
am_hal_ble_check_status(am_hal_ble_state_t * pBle)1846 am_hal_ble_check_status(am_hal_ble_state_t *pBle)
1847 {
1848 //
1849 // We need to make a special exception for "continue" packets, since the
1850 // BLE radio may deassert the STATUS signal mid-packet.
1851 //
1852 if (pBle->bContinuePacket)
1853 {
1854 pBle->bContinuePacket = false;
1855 return true;
1856 }
1857
1858 if ( BLEIFn(0)->BSTATUS_b.SPISTATUS == 0)
1859 {
1860 return false;
1861 }
1862
1863 return true;
1864 } // am_hal_ble_check_status()
1865
1866 //*****************************************************************************
1867 //
1868 // Return true if IRQ is high.
1869 //
1870 //*****************************************************************************
1871 static bool
am_hal_ble_check_irq(am_hal_ble_state_t * pBle)1872 am_hal_ble_check_irq(am_hal_ble_state_t *pBle)
1873 {
1874 if ( BLEIFn(pBle->ui32Module)->BSTATUS_b.BLEIRQ )
1875 {
1876 return true;
1877 }
1878
1879 return false;
1880 } // am_hal_ble_check_irq()
1881
1882 //*****************************************************************************
1883 //
1884 // Blocking write to the BLE module.
1885 //
1886 //*****************************************************************************
1887 uint32_t
am_hal_ble_blocking_transfer(void * pHandle,am_hal_ble_transfer_t * psTransfer)1888 am_hal_ble_blocking_transfer(void *pHandle, am_hal_ble_transfer_t *psTransfer)
1889 {
1890 am_hal_ble_state_t *pBle = pHandle;
1891 uint32_t ui32IntEnable;
1892 uint32_t ui32Module;
1893
1894 //
1895 // Check the handle.
1896 //
1897 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1898 {
1899 return AM_HAL_STATUS_INVALID_HANDLE;
1900 }
1901
1902 //
1903 // Handle is good, so get the module number.
1904 //
1905 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
1906
1907 //
1908 // If the transfer doesn't have any bytes in it, just return success.
1909 //
1910 if (psTransfer->ui16Length == 0)
1911 {
1912 return AM_HAL_STATUS_SUCCESS;
1913 }
1914
1915 //
1916 // Make sure we don't get any interrupts that might interfere with this
1917 // operation. We will save the interrupt enable register state so we can
1918 // restore it later. Also, make sure "command complete" is clear, so we can
1919 // detect the end of the transaction.
1920 //
1921 ui32IntEnable = BLEIFn(ui32Module)->INTEN;
1922 BLEIFn(ui32Module)->INTEN_b.BLECIRQ = 0;
1923 BLEIFn(ui32Module)->INTEN_b.BLECSSTAT = 0;
1924 BLEIFn(ui32Module)->INTEN_b.CMDCMP = 0;
1925 BLEIFn(ui32Module)->INTEN_b.THR = 0;
1926 BLEIFn(ui32Module)->INTCLR_b.CMDCMP = 1;
1927 BLEIFn(ui32Module)->INTCLR_b.BLECSSTAT = 1;
1928
1929 //
1930 // If we're writing, we need to lock down the bus now. Set the wakeup
1931 // signal, and start monitoring STATUS. If STATUS isn't high within our
1932 // configured timeout, we have to assume that the BLE core is unresponsive
1933 // and report an error back to the caller.
1934 //
1935 if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
1936 {
1937 uint32_t ui32SpiStatus = false;
1938
1939 if ( pBle->bLastPacketWasTX == true)
1940 {
1941 //
1942 // wait some time to give the controller more time to consume
1943 // the last TX packet
1944 //
1945 if (!pBle->bPatchComplete)
1946 {
1947 delay_ms(3);
1948 }
1949 pBle->bLastPacketWasTX = false;
1950 }
1951
1952 if (pBle->bPatchComplete)
1953 {
1954 uint32_t statusTimeout = 0;
1955 while (am_hal_ble_check_status(pBle) == true)
1956 {
1957 statusTimeout++;
1958 delay_us(10);
1959 if (statusTimeout > 300)
1960 {
1961 break;
1962 }
1963 }
1964 }
1965
1966 //
1967 // Make sure the IO clock for the STATUS signal is on.
1968 //
1969 BLEIFn(0)->BLEDBG_b.IOCLKON = 1;
1970 delay_us(5);
1971
1972 //
1973 // Set WAKE, and wait for a positive edge on the STATUS signal.
1974 //
1975 am_hal_ble_wakeup_set(pBle, 1);
1976
1977 //
1978 // If we don't see an edge on STATUS in X ms, assume it's not coming
1979 // and return with an AM_HAL_BLE_STATUS_SPI_NOT_READY error.
1980 //
1981 uint32_t ui32Timeout = 0;
1982 uint32_t ui32TimeoutLimit = AM_BLE_STATUS_TIMEOUT;
1983
1984 while (1)
1985 {
1986 if (am_hal_ble_check_status(pBle) == true)
1987 {
1988 if (am_hal_ble_bus_lock(pBle))
1989 {
1990 ui32SpiStatus = AM_HAL_STATUS_SUCCESS;
1991 break;
1992 }
1993 }
1994 else if ((ui32Timeout >= ui32TimeoutLimit) ||
1995 (BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ))
1996 {
1997 ui32SpiStatus = AM_HAL_BLE_STATUS_SPI_NOT_READY;
1998 am_hal_ble_wakeup_set(pBle, 0);
1999 break;
2000 }
2001
2002 ui32Timeout++;
2003 delay_us(10);
2004 }
2005
2006 //
2007 // Disable IOCLK
2008 //
2009 BLEIFn(0)->BLEDBG_b.IOCLKON = 0;
2010
2011 if (ui32SpiStatus != AM_HAL_STATUS_SUCCESS)
2012 {
2013 //
2014 // Restore the interrupt state.
2015 //
2016 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2017 am_hal_ble_wakeup_set(pBle, 0);
2018 return ui32SpiStatus;
2019 }
2020 }
2021 else
2022 {
2023 if (BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0)
2024 {
2025 //
2026 // Restore the interrupt state.
2027 //
2028 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2029 return AM_HAL_BLE_STATUS_IRQ_LOW;
2030 }
2031
2032 if (!am_hal_ble_bus_lock(pBle))
2033 {
2034 //
2035 // Restore the interrupt state.
2036 //
2037 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2038 return AM_HAL_BLE_STATUS_BUS_BUSY;
2039 }
2040 }
2041
2042 if (psTransfer->bContinue)
2043 {
2044 pBle->bContinuePacket = true;
2045 }
2046
2047 //
2048 // Set the current transfer, and clear the command complete interrupt so we
2049 // can tell when the next command completes.
2050 //
2051 memcpy(&pBle->sCurrentTransfer, psTransfer, sizeof(am_hal_ble_transfer_t));
2052
2053 //
2054 // Critical section to protect the gap between command and data.
2055 //
2056 AM_CRITICAL_BEGIN;
2057
2058 //
2059 // Write the command word.
2060 //
2061 am_hal_ble_cmd_write(pHandle, psTransfer);
2062
2063 //
2064 // Now we need to manage the fifos based on the type of transfer. In either
2065 // case, we will keep draining or refilling the FIFO until the full
2066 // transaction is complete.
2067 //
2068 if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
2069 {
2070 bool bCmdCmp = false;
2071 uint32_t numWait = 0;
2072 // Adjust the byte count to be sent/received for repeat count
2073 uint32_t ui32Bytes = pBle->sCurrentTransfer.ui16Length;
2074
2075 uint32_t ui32FifoRem;
2076 uint32_t *pui32Buffer = pBle->sCurrentTransfer.pui32Data;
2077
2078 //
2079 // Write the command word.
2080 //
2081 am_hal_ble_cmd_write(pHandle, psTransfer);
2082
2083 //
2084 // Keep looping until we're out of bytes to send or command complete (error).
2085 //
2086 while (ui32Bytes)
2087 {
2088 //
2089 // Limit the wait to reasonable limit - instead of blocking forever
2090 //
2091 numWait = 0;
2092 while ((ui32FifoRem = BLEIFn(ui32Module)->FIFOPTR_b.FIFO0REM) < 4)
2093 {
2094 bCmdCmp = BLEIFn(ui32Module)->INTSTAT_b.CMDCMP;
2095 if (bCmdCmp || (numWait++ >= AM_HAL_IOM_MAX_BLOCKING_WAIT))
2096 {
2097 //
2098 // FIFO not expected to change any more - get out
2099 //
2100 break;
2101 }
2102 else
2103 {
2104 am_hal_flash_delay( FLASH_CYCLES_US(1) );
2105 }
2106 }
2107 if (bCmdCmp || (ui32FifoRem < 4))
2108 {
2109 //
2110 // Something went wrong - bail out
2111 //
2112 break;
2113 }
2114
2115 while ((ui32FifoRem >= 4) && ui32Bytes)
2116 {
2117 BLEIFn(ui32Module)->FIFOPUSH = *pui32Buffer++;
2118 ui32FifoRem -= 4;
2119 if (ui32Bytes >= 4)
2120 {
2121 ui32Bytes -= 4;
2122 }
2123 else
2124 {
2125 ui32Bytes = 0;
2126 }
2127 }
2128 }
2129 WHILE_TIMEOUT_MS_BREAK ( BLEIFn(ui32Module)->INTSTAT_b.CMDCMP == 0, 2,
2130 AM_HAL_BLE_HCI_PACKET_INCOMPLETE );
2131 am_hal_ble_wakeup_set(pBle, 0);
2132 }
2133 else
2134 {
2135 while (pBle->ui32TransferIndex < pBle->sCurrentTransfer.ui16Length)
2136 {
2137 am_hal_ble_fifo_drain(pHandle);
2138 }
2139 }
2140
2141 //
2142 // End the critical section.
2143 //
2144 AM_CRITICAL_END;
2145
2146 //
2147 // Wait for the transaction to complete, and clear out any interrupts that
2148 // may have come up.
2149 //
2150 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->INTSTAT_b.CMDCMP == 0, 10,
2151 AM_HAL_BLE_HCI_PACKET_INCOMPLETE );
2152 BLEIFn(ui32Module)->INTCLR_b.CMDCMP = 1;
2153 BLEIFn(ui32Module)->INTCLR_b.THR = 1;
2154
2155 //
2156 // Clear out the current transfer. We're done.
2157 //
2158 memset(&pBle->sCurrentTransfer, 0, sizeof(am_hal_ble_transfer_t));
2159 pBle->ui32TransferIndex = 0;
2160
2161 //
2162 // Let the radio go back to sleep.
2163 //
2164 if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
2165 {
2166 am_hal_ble_wakeup_set(pBle, 0);
2167 pBle->bLastPacketWasTX = true;
2168 }
2169
2170 if ((psTransfer->ui8Command == AM_HAL_BLE_READ) &&
2171 (pBle->bPatchComplete == true))
2172 {
2173 pBle->bLastPacketWasTX = false;
2174 }
2175
2176 //
2177 // Restore the interrupt state.
2178 //
2179 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2180
2181 //
2182 // Release the bus.
2183 //
2184 am_hal_ble_bus_release(pBle);
2185
2186
2187 //
2188 // Return the status.
2189 //
2190 return AM_HAL_STATUS_SUCCESS;
2191 } // am_hal_ble_blocking_transfer()
2192
2193 //*****************************************************************************
2194 //
2195 // Nonblocking write to the BLE module.
2196 //
2197 //*****************************************************************************
2198 uint32_t
am_hal_ble_nonblocking_transfer(void * pHandle,am_hal_ble_transfer_t * psTransfer)2199 am_hal_ble_nonblocking_transfer(void *pHandle, am_hal_ble_transfer_t *psTransfer)
2200 {
2201 am_hal_ble_state_t *pBle = pHandle;
2202 uint32_t ui32Status;
2203
2204 //
2205 // Check the handle.
2206 //
2207 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2208 {
2209 return AM_HAL_STATUS_INVALID_HANDLE;
2210 }
2211
2212 //
2213 // Check to see if this is a write or a read.
2214 //
2215 if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
2216 {
2217 ui32Status = nonblocking_write(pBle, psTransfer);
2218 }
2219 else // AM_HAL_BLE_READ case.
2220 {
2221 ui32Status = nonblocking_read(pBle, psTransfer);
2222 }
2223
2224 return ui32Status;
2225 } // am_hal_ble_nonblocking_transfer()
2226
2227 //*****************************************************************************
2228 //
2229 // Function for performing non-blocking writes to the HCI interface.
2230 //
2231 // This function will start a BLE write on the physical bus. The caller should
2232 // have already set WAKEUP and received a STATUS interrupt before they call
2233 // this function. When the write operation is complete, the MCU will receive a
2234 // command complete interrupt.
2235 //
2236 // Before calling this function, the caller is responsible for ensuring that
2237 // STATUS is high, that BLEIRQ is low, and the the bus isn't already in use. If
2238 // any of these problems exists when this function is called, it will simply
2239 // return with an error status.
2240 //
2241 //*****************************************************************************
2242 static uint32_t
nonblocking_write(am_hal_ble_state_t * pBle,am_hal_ble_transfer_t * psTransfer)2243 nonblocking_write(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer)
2244 {
2245 uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
2246 uint32_t ui32Module = pBle->ui32Module;
2247
2248 //
2249 // This function goes in a critical section to make sure that the operation
2250 // isn't interrupted or started again.
2251 //
2252 AM_CRITICAL_BEGIN;
2253
2254 do
2255 {
2256 //
2257 // Check for any of the various reasons that we might not be able to
2258 // perform a write right now. If the bus is busy, if the BLE core requires
2259 // a READ operation, or if the BLE core simply isn't ready yet, stop here
2260 // and throw an error.
2261 //
2262 if ( pBle->bBusy )
2263 {
2264 ui32Status = AM_HAL_BLE_STATUS_BUS_BUSY;
2265 break;
2266 }
2267
2268 if ( am_hal_ble_check_irq(pBle) )
2269 {
2270 ui32Status = AM_HAL_BLE_REQUESTING_READ;
2271 break;
2272 }
2273
2274 if ( !am_hal_ble_check_status(pBle) )
2275 {
2276 ui32Status = AM_HAL_BLE_STATUS_SPI_NOT_READY;
2277 break;
2278 }
2279
2280 if (psTransfer->ui16Length == 0)
2281 {
2282 ui32Status = AM_HAL_STATUS_SUCCESS;
2283 break;
2284 }
2285
2286 //
2287 // With the obvious error cases out of the way, we can claim the bus and
2288 // start the transaction.
2289 //
2290 if ( pBle->bLastPacketWasTX == true )
2291 {
2292 delay_us(AM_BLE_TX_PACKET_SPACING_US);
2293 }
2294
2295 pBle->bBusy = true;
2296 pBle->bLastPacketWasTX = true;
2297
2298 //
2299 // Save the current transfer.
2300 //
2301 memcpy(&pBle->sCurrentTransfer, psTransfer, sizeof(am_hal_ble_transfer_t));
2302
2303 //
2304 // Prepare the DMA.
2305 //
2306 BLEIFn(ui32Module)->DMATARGADDR = (uint32_t)pBle->sCurrentTransfer.pui32Data;
2307 BLEIFn(ui32Module)->DMATOTCOUNT = pBle->sCurrentTransfer.ui16Length;
2308 BLEIFn(ui32Module)->DMATRIGEN = BLEIF_DMATRIGEN_DTHREN_Msk;
2309 BLEIFn(ui32Module)->DMACFG =
2310 (_VAL2FLD(BLEIF_DMACFG_DMADIR, BLEIF_DMACFG_DMADIR_M2P) |
2311 _VAL2FLD(BLEIF_DMACFG_DMAPRI, BLEIF_DMACFG_DMAPRI_HIGH));
2312
2313 //
2314 // Write the command word, and enable the DMA.
2315 //
2316 ui32Status = am_hal_ble_cmd_write(pBle, &pBle->sCurrentTransfer);
2317
2318 BLEIFn(ui32Module)->DMACFG |= _VAL2FLD(BLEIF_DMACFG_DMAEN, BLEIF_DMACFG_DMAEN_EN);
2319
2320 //
2321 // Make sure WAKE goes low as quickly as possible after starting the write.
2322 //
2323 if (ui32Status == AM_HAL_STATUS_SUCCESS)
2324 {
2325 am_hal_ble_wakeup_set(pBle, 0);
2326 }
2327 }
2328 while (0);
2329
2330 //
2331 // No matter what happened above, the function should end here. We'll end
2332 // the critical section and alert the caller of our status.
2333 //
2334 AM_CRITICAL_END;
2335 return ui32Status;
2336 } // nonblocking_write()
2337
2338 //*****************************************************************************
2339 //
2340 // This function performs a nonblocking read from the BLE core.
2341 //
2342 //*****************************************************************************
2343 static uint32_t
nonblocking_read(am_hal_ble_state_t * pBle,am_hal_ble_transfer_t * psTransfer)2344 nonblocking_read(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer)
2345 {
2346 uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
2347 uint32_t ui32Module = pBle->ui32Module;
2348
2349 //
2350 // This function goes in a critical section to make sure that the operation
2351 // isn't interrupted or started again.
2352 //
2353 AM_CRITICAL_BEGIN;
2354
2355 do
2356 {
2357 if ( pBle->bBusy )
2358 {
2359 ui32Status = AM_HAL_BLE_STATUS_BUS_BUSY;
2360 break;
2361 }
2362
2363 if ( !am_hal_ble_check_irq(pBle) )
2364 {
2365 ui32Status = AM_HAL_BLE_STATUS_IRQ_LOW;
2366 break;
2367 }
2368
2369 if (psTransfer->ui16Length == 0)
2370 {
2371 ui32Status = AM_HAL_STATUS_SUCCESS;
2372 break;
2373 }
2374
2375 //
2376 // With the obvious error cases out of the way, we can claim the bus and
2377 // start the transaction.
2378 //
2379 if ( pBle->bLastPacketWasTX == true )
2380 {
2381 delay_us(AM_BLE_TX_PACKET_SPACING_US);
2382 }
2383
2384 pBle->bBusy = true;
2385 pBle->bLastPacketWasTX = false;
2386
2387 //
2388 // Set the current transfer.
2389 //
2390 memcpy(&pBle->sCurrentTransfer, psTransfer, sizeof(am_hal_ble_transfer_t));
2391
2392 BLEIFn(ui32Module)->DMATARGADDR = (uint32_t) pBle->sCurrentTransfer.pui32Data;
2393 BLEIFn(ui32Module)->DMATOTCOUNT = pBle->sCurrentTransfer.ui16Length;
2394 BLEIFn(ui32Module)->DMATRIGEN = (BLEIF_DMATRIGEN_DTHREN_Msk | BLEIF_INTCLR_CMDCMP_Msk);
2395 BLEIFn(ui32Module)->DMACFG =
2396 (_VAL2FLD(BLEIF_DMACFG_DMADIR, BLEIF_DMACFG_DMADIR_P2M) |
2397 _VAL2FLD(BLEIF_DMACFG_DMAPRI, BLEIF_DMACFG_DMAPRI_HIGH));
2398
2399 //
2400 // Write the command word, and enable the DMA.
2401 //
2402 ui32Status = am_hal_ble_cmd_write(pBle, &pBle->sCurrentTransfer);
2403 BLEIFn(ui32Module)->DMACFG |= _VAL2FLD(BLEIF_DMACFG_DMAEN, BLEIF_DMACFG_DMAEN_EN);
2404 }
2405 while (0);
2406
2407 //
2408 // No matter what happened above, the function should end here. We'll end
2409 // the critical section and alert the caller of our status.
2410 //
2411 AM_CRITICAL_END;
2412 return ui32Status;
2413 } // nonblocking_read()
2414
2415 //*****************************************************************************
2416 //
2417 // Mark the BLE interface busy so it doesn't get used by more than one
2418 // interface.
2419 //
2420 //*****************************************************************************
2421 static bool
am_hal_ble_bus_lock(am_hal_ble_state_t * pBle)2422 am_hal_ble_bus_lock(am_hal_ble_state_t *pBle)
2423 {
2424 bool bLockObtained;
2425
2426 //
2427 // In one atomic sweep, check to see if the bus is busy, and reserve it if
2428 // it isn't.
2429 //
2430 AM_CRITICAL_BEGIN;
2431
2432 if (pBle->bBusy == false)
2433 {
2434 am_hal_debug_gpio_set(BLE_DEBUG_TRACE_11);
2435 pBle->bBusy = true;
2436 bLockObtained = true;
2437 pBle->bCmdComplete = 0;
2438 pBle->bDmaComplete = 0;
2439 pBle->bFlowControlComplete = 0;
2440 }
2441 else
2442 {
2443 bLockObtained = false;
2444 }
2445
2446 AM_CRITICAL_END;
2447
2448 //
2449 // Tell the caller if we successfully locked the bus.
2450 //
2451 return bLockObtained;
2452 } // am_hal_ble_bus_lock()
2453
2454 //*****************************************************************************
2455 //
2456 // Release the bus so someone else can use it.
2457 //
2458 //*****************************************************************************
2459 static void
am_hal_ble_bus_release(am_hal_ble_state_t * pBle)2460 am_hal_ble_bus_release(am_hal_ble_state_t *pBle)
2461 {
2462 pBle->bBusy = false;
2463 am_hal_debug_gpio_clear(BLE_DEBUG_TRACE_11);
2464 }
2465
2466 //*****************************************************************************
2467 //
2468 // Pull data out of the fifo for reads.
2469 //
2470 //*****************************************************************************
2471 static uint32_t
am_hal_ble_fifo_drain(void * pHandle)2472 am_hal_ble_fifo_drain(void *pHandle)
2473 {
2474 uint32_t ui32Module;
2475 uint32_t ui32ReadSize, ui32RxDataLen, ui32BytesLeft;
2476 uint32_t *pDest;
2477
2478 //
2479 // Check the handle.
2480 //
2481 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2482 {
2483 return 0;
2484 }
2485
2486 //
2487 // Handle is good, so get the module number.
2488 //
2489 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2490
2491 //
2492 // Rename some pointers for convenience.
2493 //
2494 am_hal_ble_state_t *pBle = pHandle;
2495 am_hal_ble_transfer_t *pTransfer = &pBle->sCurrentTransfer;
2496
2497 //
2498 // Check to see how much data there is in the FIFO, and also how many
2499 // bytes are remaining in the transfer.
2500 //
2501 ui32RxDataLen = BLEIFn(ui32Module)->FIFOPTR_b.FIFO1SIZ;
2502 ui32BytesLeft = (pTransfer->ui16Length - pBle->ui32TransferIndex);
2503
2504 //
2505 // Calculate how much we can drain the fifo.
2506 //
2507 if (ui32RxDataLen < 4)
2508 {
2509 return 0;
2510 }
2511 else if (ui32RxDataLen >= pTransfer->ui16Length)
2512 {
2513 ui32ReadSize = ui32BytesLeft;
2514 }
2515 else
2516 {
2517 ui32ReadSize = ui32RxDataLen & (~0x3);
2518 }
2519
2520 //
2521 // Calculate the place where we last left off, feed the FIFO starting from
2522 // that location, and update the index to match.
2523 //
2524 pDest = &pTransfer->pui32Data[pBle->ui32TransferIndex / 4];
2525
2526 am_hal_ble_fifo_read(pHandle, pDest, ui32ReadSize);
2527
2528 pBle->ui32TransferIndex += ui32ReadSize;
2529
2530 //
2531 // Return the number of bytes we wrote.
2532 //
2533 return ui32ReadSize;
2534 } // am_hal_ble_fifo_drain()
2535
2536 //*****************************************************************************
2537 //
2538 // Write the command word for a BLE transfer.
2539 //
2540 //*****************************************************************************
2541 uint32_t
am_hal_ble_cmd_write(void * pHandle,am_hal_ble_transfer_t * psTransfer)2542 am_hal_ble_cmd_write(void *pHandle, am_hal_ble_transfer_t *psTransfer)
2543 {
2544 uint32_t ui32CmdWord, ui32OffsetHigh;
2545 uint32_t ui32Module;
2546
2547 //
2548 // Check the handle.
2549 //
2550 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2551 {
2552 return AM_HAL_STATUS_INVALID_HANDLE;
2553 }
2554
2555 //
2556 // Handle is good, so get the module number.
2557 //
2558 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2559
2560 //
2561 // Figure out the command word and the offset register. Then write them.
2562 //
2563 switch (psTransfer->ui8OffsetLen)
2564 {
2565 case 0:
2566 ui32CmdWord = 0;
2567 ui32OffsetHigh = 0;
2568 break;
2569
2570 case 1:
2571 ui32CmdWord = _VAL2FLD(BLEIF_CMD_OFFSETLO, psTransfer->pui8Offset[0]);
2572 ui32OffsetHigh = 0;
2573 break;
2574
2575 case 2:
2576 ui32CmdWord = _VAL2FLD(BLEIF_CMD_OFFSETLO, psTransfer->pui8Offset[1]);
2577 ui32OffsetHigh = psTransfer->pui8Offset[0];
2578 break;
2579
2580 case 3:
2581 ui32CmdWord = _VAL2FLD(BLEIF_CMD_OFFSETLO, psTransfer->pui8Offset[2]);
2582 ui32OffsetHigh = ((psTransfer->pui8Offset[1]) |
2583 (psTransfer->pui8Offset[0] << 8));
2584 break;
2585
2586 default:
2587 // Offset length was incorrect.
2588 return AM_HAL_STATUS_INVALID_ARG;
2589 }
2590
2591 ui32CmdWord |= (_VAL2FLD(BLEIF_CMD_OFFSETCNT, psTransfer->ui8OffsetLen) |
2592 _VAL2FLD(BLEIF_CMD_TSIZE, psTransfer->ui16Length) |
2593 _VAL2FLD(BLEIF_CMD_CONT, psTransfer->bContinue) |
2594 psTransfer->ui8Command);
2595
2596 BLEIFn(ui32Module)->OFFSETHI = ui32OffsetHigh;
2597 BLEIFn(ui32Module)->CMD = ui32CmdWord;
2598
2599 //
2600 // Return the status.
2601 //
2602 return AM_HAL_STATUS_SUCCESS;
2603 } // am_hal_ble_cmd_write()
2604
2605 //*****************************************************************************
2606 //
2607 // Read ui32NumBytes from the RX FIFO.
2608 //
2609 //*****************************************************************************
2610 static void
am_hal_ble_fifo_read(void * pHandle,uint32_t * pui32Data,uint32_t ui32NumBytes)2611 am_hal_ble_fifo_read(void *pHandle, uint32_t *pui32Data, uint32_t ui32NumBytes)
2612 {
2613 uint32_t ui32Index;
2614 uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2615
2616 for (ui32Index = 0; (ui32Index * 4) < ui32NumBytes; ui32Index++)
2617 {
2618 pui32Data[ui32Index] = BLEIFn(ui32Module)->FIFOPOP;
2619
2620 #ifndef AM_HAL_BLE_NO_FIFO_PROTECTION
2621 BLEIFn(ui32Module)->FIFOPOP = 0;
2622 #endif
2623
2624 }
2625 } // am_hal_ble_fifo_read()
2626
2627 //*****************************************************************************
2628 //
2629 // Call the appropriate callbacks when DMA transfers complete.
2630 //
2631 //*****************************************************************************
2632 uint32_t
am_hal_ble_int_service(void * pHandle,uint32_t ui32Status)2633 am_hal_ble_int_service(void *pHandle, uint32_t ui32Status)
2634 {
2635 am_hal_ble_state_t *pBle = pHandle;
2636 uint32_t ui32Module;
2637
2638 //
2639 // Check the handle.
2640 //
2641 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2642 {
2643 return AM_HAL_STATUS_INVALID_HANDLE;
2644 }
2645
2646 //
2647 // The handle is good, so get the module number.
2648 //
2649 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2650
2651 //
2652 // Track each of the interrupts signaling the end of an HCI transfer.
2653 //
2654 if ( ui32Status & BLEIF_INTSTAT_CMDCMP_Msk )
2655 {
2656 pBle->bCmdComplete = true;
2657 }
2658
2659 if ( ui32Status & BLEIF_INTSTAT_DCMP_Msk )
2660 {
2661 pBle->bDmaComplete = true;
2662 }
2663
2664 //
2665 // For B0 parts, we can detect when key flow control signals from the BLE
2666 // core are de-asserted.
2667 //
2668 if (APOLLO3_B0 || APOLLO3_GE_B0)
2669 {
2670 //
2671 // Check for falling IRQ
2672 //
2673 if ( (ui32Status & BLEIF_INTSTAT_BLECIRQN_Msk) &&
2674 (pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_READ) )
2675 {
2676 pBle->bFlowControlComplete = true;
2677 }
2678
2679 //
2680 // Check for falling status.
2681 //
2682 if ( (ui32Status & BLEIF_INTSTAT_BLECSSTATN_Msk ) &&
2683 (pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_WRITE) )
2684 {
2685 pBle->bFlowControlComplete = true;
2686 }
2687 }
2688 else
2689 {
2690 return AM_HAL_STATUS_FAIL;
2691 }
2692
2693 //
2694 // If we get a command complete, we need to release the wake signal,
2695 // disable the DMA, release the bus, and call any callback that might
2696 // exist.
2697 //
2698 // For revision A parts, "command complete" means that the DMA operation
2699 // and the BLE SPI interface have both finished their operations. For rev B
2700 // parts, we will also wait for the flow control signal (either STATUS or
2701 // IRQ) to be removed.
2702 //
2703 if ( pBle->bCmdComplete && pBle->bDmaComplete &&
2704 ((pBle->bFlowControlComplete) || (!APOLLO3_GE_B0) || SKIP_FALLING_EDGES) )
2705 {
2706 //
2707 // Clean up our state flags.
2708 //
2709 pBle->bCmdComplete = false;
2710 pBle->bDmaComplete = false;
2711 pBle->bFlowControlComplete = false;
2712
2713 //
2714 // If our FIFOs aren't empty right now, either the DMA didn't finish,
2715 // or this interrupt handler is somehow being called incorrectly.
2716 //
2717 if ( BLEIFn(ui32Module)->FIFOPTR != 0x20002000 )
2718 {
2719 return AM_HAL_BLE_FIFO_ERROR;
2720 }
2721
2722 //
2723 // Drop the wake request if we had one, and make sure we remember if
2724 // the last packet was a transmit packet.
2725 //
2726 if ((pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_WRITE) &&
2727 (pBle->bPatchComplete == true))
2728 {
2729 pBle->bLastPacketWasTX = true;
2730 am_hal_ble_wakeup_set(pBle, 0);
2731 }
2732
2733 //
2734 // If this was a read packet, remember that it wasn't a TX packet.
2735 //
2736 if (pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_READ)
2737 {
2738 pBle->bLastPacketWasTX = false;
2739 }
2740
2741 //
2742 // Disable the DMA
2743 //
2744 BLEIFn(ui32Module)->DMACFG = 0;
2745
2746 am_hal_ble_bus_release(pBle);
2747
2748 if ( pBle->sCurrentTransfer.pfnTransferCompleteCB )
2749 {
2750 am_hal_ble_transfer_complete_cb_t pfnCallback;
2751 uint32_t ui32Length;
2752 uint8_t *pui8Data;
2753 void *pvContext;
2754
2755 pfnCallback = pBle->sCurrentTransfer.pfnTransferCompleteCB;
2756 pui8Data = (uint8_t * ) pBle->sCurrentTransfer.pui32Data;
2757 ui32Length = pBle->sCurrentTransfer.ui16Length;
2758 pvContext = pBle->sCurrentTransfer.pvContext;
2759
2760 pfnCallback(pui8Data, ui32Length, pvContext);
2761 }
2762 }
2763
2764 //
2765 // Return the status.
2766 //
2767 return AM_HAL_STATUS_SUCCESS;
2768 } // am_hal_ble_int_service()
2769
2770 //*****************************************************************************
2771 //
2772 // Interrupt Enable
2773 //
2774 //*****************************************************************************
2775 uint32_t
am_hal_ble_int_enable(void * pHandle,uint32_t ui32InterruptMask)2776 am_hal_ble_int_enable(void *pHandle, uint32_t ui32InterruptMask)
2777 {
2778 uint32_t ui32Module;
2779
2780 //
2781 // Check the handle.
2782 //
2783 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2784 {
2785 return AM_HAL_STATUS_INVALID_HANDLE;
2786 }
2787
2788 //
2789 // Handle is good, so get the module number.
2790 //
2791 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2792
2793 AM_CRITICAL_BEGIN
2794 BLEIFn(ui32Module)->INTEN |= ui32InterruptMask;
2795 AM_CRITICAL_END
2796
2797 //
2798 // Return the status.
2799 //
2800 return AM_HAL_STATUS_SUCCESS;
2801 } // am_hal_ble_int_enable()
2802
2803 //*****************************************************************************
2804 //
2805 // Interrupt Enable
2806 //
2807 //*****************************************************************************
2808 uint32_t
am_hal_ble_int_disable(void * pHandle,uint32_t ui32InterruptMask)2809 am_hal_ble_int_disable(void *pHandle, uint32_t ui32InterruptMask)
2810 {
2811 uint32_t ui32Module;
2812
2813 //
2814 // Check the handle.
2815 //
2816 if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2817 {
2818 return AM_HAL_STATUS_INVALID_HANDLE;
2819 }
2820
2821 //
2822 // Handle is good, so get the module number.
2823 //
2824 ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2825
2826 AM_CRITICAL_BEGIN
2827 BLEIFn(ui32Module)->INTEN &= ~ui32InterruptMask;
2828 AM_CRITICAL_END
2829
2830 //
2831 // Return the status.
2832 //
2833 return AM_HAL_STATUS_SUCCESS;
2834 } // am_hal_ble_int_disable()
2835
2836 //*****************************************************************************
2837 //
2838 // Check the status of the interrupts.
2839 //
2840 //*****************************************************************************
2841 uint32_t
am_hal_ble_int_status(void * pHandle,bool bEnabledOnly)2842 am_hal_ble_int_status(void *pHandle, bool bEnabledOnly)
2843 {
2844 uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2845
2846 if (bEnabledOnly)
2847 {
2848 uint32_t ui32IntEn = BLEIFn(ui32Module)->INTEN;
2849 return ( BLEIFn(ui32Module)->INTSTAT & ui32IntEn );
2850 }
2851 else
2852 {
2853 return BLEIFn(ui32Module)->INTSTAT;
2854 }
2855 } // am_hal_ble_int_status()
2856
2857 //*****************************************************************************
2858 //
2859 // Clear the interrupt status.
2860 //
2861 //*****************************************************************************
2862 uint32_t
am_hal_ble_int_clear(void * pHandle,uint32_t ui32InterruptMask)2863 am_hal_ble_int_clear(void *pHandle, uint32_t ui32InterruptMask)
2864 {
2865 uint32_t ui32Module;
2866
2867 //
2868 // Check the handle.
2869 //
2870 if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
2871 {
2872 return AM_HAL_STATUS_INVALID_HANDLE;
2873 }
2874
2875 //
2876 // Handle is good, so get the module number.
2877 //
2878 ui32Module = ((am_hal_ble_state_t *)pHandle)->ui32Module;
2879
2880 BLEIFn(ui32Module)->INTCLR = ui32InterruptMask;
2881
2882 //
2883 // Return the status.
2884 //
2885 return AM_HAL_STATUS_SUCCESS;
2886 } // am_hal_ble_int_clear()
2887
2888 //*****************************************************************************
2889 //
2890 // check 32768Hz clock is ready.
2891 //
2892 //*****************************************************************************
2893 uint32_t
am_hal_ble_check_32k_clock(void * pHandle)2894 am_hal_ble_check_32k_clock(void *pHandle)
2895 {
2896 am_hal_ble_state_t *pBLE = pHandle;
2897 uint32_t rc32k_clock = 0xFFFFFFFF;
2898
2899 if (APOLLO3_B0)
2900 {
2901 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_B0, &rc32k_clock);
2902 }
2903 else
2904 {
2905 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_A1, &rc32k_clock);
2906 }
2907
2908 // Normal 32KHz clock is about 0x8000
2909 if ( (rc32k_clock > 0x8200) || (rc32k_clock < 0x7B00) )
2910 {
2911 return AM_HAL_STATUS_FAIL;
2912 }
2913 else
2914 {
2915 return AM_HAL_STATUS_SUCCESS;
2916 }
2917 } // am_hal_ble_check_32k_clock()
2918
2919 //*****************************************************************************
2920 //
2921 // Read a register value from the BLE core.
2922 //
2923 //*****************************************************************************
2924 uint32_t
am_hal_ble_plf_reg_read(void * pHandle,uint32_t ui32Address,uint32_t * pui32Value)2925 am_hal_ble_plf_reg_read(void *pHandle, uint32_t ui32Address, uint32_t *pui32Value)
2926 {
2927 am_hal_ble_state_t *pBLE = pHandle;
2928 uint8_t pui8Parameter[4];
2929 uint32_t ui32IntEnable;
2930
2931 uint32_t ui32Module = pBLE->ui32Module;
2932
2933 //
2934 // Make a buffer big enough to hold the register write command, and a
2935 // second one big enough to hold the response.
2936 //
2937 am_hal_ble_buffer(AM_HAL_BLE_PLF_REGISTER_READ_LENGTH) sWriteCommand;
2938 am_hal_ble_buffer(32) sResponse;
2939
2940 //
2941 // Prepare our register write value.
2942 //
2943 pui8Parameter[0] = ui32Address;
2944 pui8Parameter[1] = (ui32Address >> 8);
2945 pui8Parameter[2] = (ui32Address >> 16);
2946 pui8Parameter[3] = (ui32Address >> 24);
2947
2948 sResponse.words[0] = 0;
2949 sResponse.words[1] = 0;
2950 sResponse.words[2] = 0;
2951
2952 //
2953 // Fill the buffer with the specific command we want to write, and send it.
2954 //
2955 am_hal_ble_vs_command_build(sWriteCommand.words,
2956 AM_HAL_BLE_PLF_REGISTER_READ_OPCODE,
2957 AM_HAL_BLE_PLF_REGISTER_READ_LENGTH,
2958 pui8Parameter);
2959
2960 //
2961 // Temporarily disable BLE interrupts.
2962 //
2963 ui32IntEnable = BLEIFn(ui32Module)->INTEN;
2964 BLEIFn(ui32Module)->INTEN = 0;
2965
2966 am_hal_ble_blocking_hci_write(pBLE,
2967 AM_HAL_BLE_RAW,
2968 sWriteCommand.words,
2969 AM_HAL_BLE_PLF_REGISTER_READ_LENGTH);
2970
2971 //
2972 // Make sure the IO clock for the STATUS signal is on.
2973 //
2974 BLEIFn(ui32Module)->BLEDBG_b.IOCLKON = 1;
2975
2976 //
2977 // Wait for the response, and return it to the caller via our variable.
2978 //
2979 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 500,
2980 AM_HAL_BLE_NO_HCI_RESPONSE );
2981
2982 am_hal_ble_blocking_hci_read(pBLE, sResponse.words, 0);
2983
2984 *pui32Value = (((sResponse.words[1] & 0xFF000000) >> 24) |
2985 ((sResponse.words[2] & 0x00FFFFFF) << 8));
2986
2987 //
2988 // Re-enable BLE interrupts.
2989 //
2990 BLEIFn(ui32Module)->INTCLR = ui32IntEnable;
2991 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2992
2993 return AM_HAL_STATUS_SUCCESS;
2994
2995 } // am_hal_ble_plf_reg_read()
2996
2997 //*****************************************************************************
2998 //
2999 // Write a register value to the BLE core.
3000 //
3001 //*****************************************************************************
3002 uint32_t
am_hal_ble_plf_reg_write(void * pHandle,uint32_t ui32Address,uint32_t ui32Value)3003 am_hal_ble_plf_reg_write(void *pHandle, uint32_t ui32Address, uint32_t ui32Value)
3004 {
3005 am_hal_ble_state_t *pBLE = pHandle;
3006 uint8_t pui8Parameter[8];
3007 uint32_t ui32IntEnable;
3008
3009 uint32_t ui32Module = pBLE->ui32Module;
3010
3011 //
3012 // Make a buffer big enough to hold the register write command, and a
3013 // second one big enough to hold the response.
3014 //
3015 am_hal_ble_buffer(AM_HAL_BLE_PLF_REGISTER_WRITE_LENGTH) sWriteCommand;
3016 am_hal_ble_buffer(16) sResponse;
3017
3018 //
3019 // Prepare our register write value.
3020 //
3021 pui8Parameter[0] = ui32Address;
3022 pui8Parameter[1] = (ui32Address >> 8);
3023 pui8Parameter[2] = (ui32Address >> 16);
3024 pui8Parameter[3] = (ui32Address >> 24);
3025 pui8Parameter[4] = ui32Value;
3026 pui8Parameter[5] = (ui32Value >> 8);
3027 pui8Parameter[6] = (ui32Value >> 16);
3028 pui8Parameter[7] = (ui32Value >> 24);
3029
3030 //
3031 // Fill the buffer with the specific command we want to write, and send it.
3032 //
3033 am_hal_ble_vs_command_build(sWriteCommand.words,
3034 AM_HAL_BLE_PLF_REGISTER_WRITE_OPCODE,
3035 AM_HAL_BLE_PLF_REGISTER_WRITE_LENGTH,
3036 pui8Parameter);
3037
3038 //
3039 // Temporarily disable BLE interrupts.
3040 //
3041 ui32IntEnable = BLEIFn(ui32Module)->INTEN;
3042 BLEIFn(ui32Module)->INTEN = 0;
3043
3044 am_hal_ble_blocking_hci_write(pBLE,
3045 AM_HAL_BLE_RAW,
3046 sWriteCommand.words,
3047 AM_HAL_BLE_PLF_REGISTER_WRITE_LENGTH);
3048
3049 //
3050 // Make sure the IO clock for the STATUS signal is on.
3051 //
3052 BLEIFn(ui32Module)->BLEDBG_b.IOCLKON = 1;
3053
3054 //
3055 // Wait for the response.
3056 //
3057 WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 50,
3058 AM_HAL_BLE_NO_HCI_RESPONSE );
3059
3060 am_hal_ble_blocking_hci_read(pBLE, sResponse.words, 0);
3061
3062 //
3063 // Re-enable BLE interrupts.
3064 //
3065 BLEIFn(ui32Module)->INTCLR = ui32IntEnable;
3066 BLEIFn(ui32Module)->INTEN = ui32IntEnable;
3067
3068 return AM_HAL_STATUS_SUCCESS;
3069
3070 } // am_hal_ble_plf_reg_write()
3071
3072 //*****************************************************************************
3073 //
3074 // Set the modulation frequency offset from INFO1,
3075 // based on the tested values stored in non-volatile memory.
3076 //
3077 //*****************************************************************************
3078 uint32_t
am_hal_ble_load_modex_trim_set(void * pHandle)3079 am_hal_ble_load_modex_trim_set(void *pHandle)
3080 {
3081 uint8_t ui8TrimValue;
3082 //
3083 // load the modex trim data from info1.
3084 //
3085 ui8TrimValue = am_hal_ble_read_trimdata_from_info1();
3086 if ( ui8TrimValue )
3087 {
3088 am_hal_ble_transmitter_modex_set(pHandle, ui8TrimValue);
3089 return AM_HAL_STATUS_SUCCESS;
3090 }
3091 else
3092 {
3093 return AM_HAL_STATUS_FAIL;
3094 }
3095 } // am_hal_ble_load_modex_trim_set()
3096
3097 //*****************************************************************************
3098 //
3099 // Load the modulation frequency offset from INFO1,
3100 // based on the tested values stored in non-volatile memory.
3101 //
3102 //*****************************************************************************
3103 uint8_t
am_hal_ble_read_trimdata_from_info1(void)3104 am_hal_ble_read_trimdata_from_info1(void)
3105 {
3106 uint32_t ui32TrimValue = 0, temp = 0;
3107 uint8_t TrimData = 0;
3108
3109 temp = ui32TrimValue = AM_REGVAL(0x50023808);
3110 temp &= 0xffffff00;
3111
3112 if ( temp == 0x18240600 )
3113 {
3114 TrimData = ui32TrimValue & 0xFF;
3115 }
3116 else
3117 {
3118 TrimData = 0;
3119 }
3120
3121 if ( (TrimData > 0x50) || (TrimData < 0x20) ) // change from 0x40 to 0x50 for improving the FT2 yield.
3122 {
3123 TrimData = 0;
3124 }
3125
3126 return TrimData;
3127 } // am_hal_ble_read_trimdata_from_info1()
3128
3129 //*****************************************************************************
3130 //
3131 // Manually set modulation characteristic
3132 // based on the tested values at customer side.
3133 // manually set frequency offset for 10101010 or 01010101 pattern
3134 // parameter default value is 0x34, increase to get larger frequency offset
3135 //
3136 //*****************************************************************************
3137 uint32_t
am_hal_ble_transmitter_modex_set(void * pHandle,uint8_t ui8ModFrqOffset)3138 am_hal_ble_transmitter_modex_set(void *pHandle, uint8_t ui8ModFrqOffset)
3139 {
3140 am_hal_ble_state_t *pBLE = pHandle;
3141 uint32_t RegValueMCGR, RegValueBACKCR, RegValueSTCR, RegValueDACSPICR, temp = 0;
3142
3143 ui8ModFrqOffset &= 0x7F;
3144
3145 am_hal_ble_plf_reg_read(pBLE, 0x43000004, &RegValueMCGR);
3146
3147 //
3148 // Unlock the BLE registers.
3149 //
3150 am_hal_ble_plf_reg_write(pBLE, 0x43000004, 0xFFFFFFFF);
3151 am_hal_ble_plf_reg_read(pBLE, 0x52000008, &temp);
3152 temp |= 0x08;
3153 am_hal_ble_plf_reg_read(pBLE, 0x52000000, &RegValueSTCR);
3154 RegValueSTCR |= (1 << 10);
3155 am_hal_ble_plf_reg_write(pBLE, 0x52000000, RegValueSTCR);
3156
3157 am_hal_ble_plf_reg_read(pBLE, 0x45800070, &RegValueBACKCR);
3158 am_hal_ble_plf_reg_write(pBLE, 0x45800070, (RegValueBACKCR | 0x8));
3159 RegValueDACSPICR = (ui8ModFrqOffset << 1) | 0x1;
3160 am_hal_ble_plf_reg_write(pBLE, 0x52000014, RegValueDACSPICR);
3161
3162 am_hal_ble_plf_reg_write(pBLE, 0x52000008, temp);
3163
3164 if (APOLLO3_B0)
3165 {
3166 am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_B0, ui8ModFrqOffset);
3167 }
3168 else
3169 {
3170 am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_A1, ui8ModFrqOffset);
3171 }
3172 am_hal_ble_plf_reg_write(pBLE, 0x43000004, RegValueMCGR);
3173
3174 return AM_HAL_STATUS_SUCCESS;
3175 } // am_hal_ble_transmitter_modex_set()
3176
3177 //*****************************************************************************
3178 //
3179 // Set BLE sleep enable/disable for the BLE core.
3180 // enable = 'true' set sleep enable, enable = 'false' set sleep disable
3181 //
3182 //*****************************************************************************
3183 uint32_t
am_hal_ble_sleep_set(void * pHandle,bool enable)3184 am_hal_ble_sleep_set(void *pHandle, bool enable)
3185 {
3186 am_hal_ble_state_t *pBLE = pHandle;
3187 uint32_t sleepenable = 0;
3188
3189 if (APOLLO3_B0)
3190 {
3191 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0, &sleepenable);
3192 }
3193 else
3194 {
3195 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1, &sleepenable);
3196 }
3197
3198 sleepenable &= 0xffff0100;
3199
3200 if ( enable )
3201 {
3202 sleepenable |= 0x0101;
3203 }
3204
3205 if (APOLLO3_B0)
3206 {
3207 am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0, sleepenable);
3208 }
3209 else
3210 {
3211 am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1, sleepenable);
3212 }
3213
3214 return AM_HAL_STATUS_SUCCESS;
3215 } // am_hal_ble_sleep_set()
3216
3217 //*****************************************************************************
3218 //
3219 // Get current sleep enable status
3220 // return 'true' = sleep enable , 'false' = sleep disable
3221 //
3222 //*****************************************************************************
3223 bool
am_hal_ble_sleep_get(void * pHandle)3224 am_hal_ble_sleep_get(void *pHandle)
3225 {
3226 am_hal_ble_state_t *pBLE = pHandle;
3227 uint32_t sleepenable = 0;
3228
3229 if (APOLLO3_B0)
3230 {
3231 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0, &sleepenable);
3232 }
3233 else
3234 {
3235 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1, &sleepenable);
3236 }
3237
3238 if ( (sleepenable & 0xFFFF) > 0 )
3239 {
3240 return true;
3241 }
3242
3243 return false;
3244 } // am_hal_ble_sleep_get()
3245
3246 //*****************************************************************************
3247 //
3248 // set the tx power of BLE
3249 // values.
3250 // ui32TxPower: 0x04->-10dBm 0x05->-5dBm 0x08->0dBm 0x0F->3dBm
3251 //
3252 //*****************************************************************************
3253 uint32_t
am_hal_ble_tx_power_set(void * pHandle,uint8_t ui32TxPower)3254 am_hal_ble_tx_power_set(void *pHandle, uint8_t ui32TxPower)
3255 {
3256 am_hal_ble_state_t *pBLE = pHandle;
3257 uint32_t RegValueMCGR, tempreg = 0;
3258 uint32_t ui32PowerValue = 0x00000008;
3259 ui32PowerValue |= (ui32TxPower & 0xF) << 16;
3260
3261 am_hal_ble_plf_reg_read(pBLE, 0x43000004, &RegValueMCGR);
3262
3263 //
3264 // Unlock the BLE controller registers.
3265 //
3266 am_hal_ble_plf_reg_write(pBLE, 0x43000004, 0xFFFFFFFF);
3267
3268 // set tx power register at 0x52400018
3269 am_hal_ble_plf_reg_write(pBLE, 0x52400018, ui32PowerValue);
3270
3271 // Lock BLE controller registers
3272 am_hal_ble_plf_reg_write(pBLE, 0x43000004, RegValueMCGR);
3273
3274 //
3275 // Update BLE controller RAM settings as well.
3276 // Note:
3277 // Register values may be lost when BLE controller enters deepsleep.
3278 // BLE controller loads RAM settings back upon wakeup.
3279 // To retain the setting, BLE controller RAM settings should be updated.
3280 //
3281 if (APOLLO3_B0)
3282 {
3283 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_B0, &tempreg);
3284 }
3285 else
3286 {
3287 am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_A1, &tempreg);
3288 }
3289
3290 tempreg &= 0xffffff00;
3291 tempreg |= ui32TxPower;
3292
3293 if (APOLLO3_B0)
3294 {
3295 am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_B0, tempreg);
3296 }
3297 else
3298 {
3299 am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_A1, tempreg);
3300 }
3301
3302 return AM_HAL_STATUS_SUCCESS;
3303 } // am_hal_ble_tx_power_set()
3304
3305 //*****************************************************************************
3306 //
3307 // End Doxygen group.
3308 //! @}
3309 //
3310 //*****************************************************************************
3311