1 //*****************************************************************************
2 //
3 //! @file am_apollo3_bt_support.c
4 //!
5 //! @brief Bluetooth support for the Apollo3 Blue Series SOC.
6 //
7 //*****************************************************************************
8
9 //*****************************************************************************
10 //
11 // Copyright (c) 2024, Ambiq Micro, Inc.
12 // All rights reserved.
13 //
14 // Redistribution and use in source and binary forms, with or without
15 // modification, are permitted provided that the following conditions are met:
16 //
17 // 1. Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimer.
19 //
20 // 2. Redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the name of the copyright holder nor the names of its
25 // contributors may be used to endorse or promote products derived from this
26 // software without specific prior written permission.
27 //
28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 // POSSIBILITY OF SUCH DAMAGE.
39 //
40 //*****************************************************************************
41
42 #include <stdint.h>
43 #include <stdbool.h>
44 #include <string.h>
45
46 #include <zephyr/kernel.h>
47
48 #include "am_mcu_apollo.h"
49 #include "am_apollo3_bt_support.h"
50
51 #define XTAL_STABILITY_MAX_RETRIES 10
52
53 //*****************************************************************************
54 //
55 // Global variables.
56 //
57 //*****************************************************************************
58
59 // BLE module handle
60 static void *BLE;
61
62 extern am_hal_ble_state_t g_sBLEState[];
63
64 //*****************************************************************************
65 //
66 // Initialize the Apollo3x BLE controller driver.
67 //
68 //*****************************************************************************
am_apollo3_bt_controller_init(void)69 uint32_t am_apollo3_bt_controller_init(void)
70 {
71 uint32_t ui32NumXtalRetries = 0;
72
73 if (g_sBLEState[0].prefix.s.bInit)
74 {
75 BLE = &g_sBLEState[0];
76 }
77 else
78 {
79 return AM_HAL_STATUS_FAIL;
80 }
81
82 //
83 // Configure and enable the BLE interface.
84 //
85 uint32_t ui32Status = AM_HAL_STATUS_FAIL;
86 while (ui32Status != AM_HAL_STATUS_SUCCESS)
87 {
88 am_hal_ble_config(BLE, &am_hal_ble_default_config);
89 //
90 // Delay 1s for 32768Hz clock stability. This isn't required unless this is
91 // our first run immediately after a power-up.
92 //
93 k_sleep(K_SECONDS(1));
94
95 //
96 // Attempt to boot the radio.
97 //
98 ui32Status = am_hal_ble_boot(BLE);
99
100 //
101 // Check our status.
102 //
103 if (ui32Status == AM_HAL_STATUS_SUCCESS)
104 {
105 //
106 // If the radio is running, we can exit this loop.
107 //
108 break;
109 }
110 else if (ui32Status == AM_HAL_BLE_32K_CLOCK_UNSTABLE)
111 {
112 //
113 // If the radio is running, but the clock looks bad, we can try to
114 // restart.
115 //
116 am_hal_ble_power_control(BLE, AM_HAL_BLE_POWER_OFF);
117 am_hal_ble_deinitialize(BLE);
118
119 //
120 // We won't restart forever. After we hit the maximum number of
121 // retries, we'll just return with failure.
122 //
123 if (ui32NumXtalRetries++ < XTAL_STABILITY_MAX_RETRIES)
124 {
125 k_sleep(K_SECONDS(1));
126 am_hal_ble_initialize(0, &BLE);
127 am_hal_ble_power_control(BLE, AM_HAL_BLE_POWER_ACTIVE);
128 }
129 else
130 {
131 return AM_HAL_STATUS_FAIL;
132 }
133 }
134 else
135 {
136 am_hal_ble_power_control(BLE, AM_HAL_BLE_POWER_OFF);
137 am_hal_ble_deinitialize(BLE);
138 //
139 // If the radio failed for some reason other than 32K Clock
140 // instability, we should just report the failure and return.
141 //
142 return AM_HAL_STATUS_FAIL;
143 }
144 }
145
146 //
147 // Set the BLE TX Output power to 0dBm.
148 //
149 am_hal_ble_tx_power_set(BLE, TX_POWER_LEVEL_0P0_dBm);
150
151 am_hal_ble_int_clear(BLE, (AM_HAL_BLE_INT_CMDCMP |
152 AM_HAL_BLE_INT_DCMP |
153 AM_HAL_BLE_INT_BLECIRQ));
154
155 am_hal_ble_int_enable(BLE, (AM_HAL_BLE_INT_CMDCMP |
156 AM_HAL_BLE_INT_DCMP |
157 AM_HAL_BLE_INT_BLECIRQ));
158
159 return AM_HAL_STATUS_SUCCESS;
160 }
161
162 //*****************************************************************************
163 //
164 // BLE ISR preprocessing.
165 //
166 //*****************************************************************************
am_apollo3_bt_isr_pre(void)167 void am_apollo3_bt_isr_pre(void)
168 {
169 uint32_t ui32Status = am_hal_ble_int_status(BLE, true);
170 am_hal_ble_int_clear(BLE, ui32Status);
171 }
172