1 //*****************************************************************************
2 //
3 //! @file am_devices_cooper.c
4 //!
5 //! @brief An implementation of the Apollo inteface to Cooper using the IOM.
6 //!
7 //! @addtogroup cooper Cooper BLE Device Driver
8 //! @ingroup devices
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, 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_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include <string.h>
51
52 #include "am_mcu_apollo.h"
53 #include "am_devices_cooper.h"
54
55 #include <zephyr/kernel.h>
56 #include <zephyr/logging/log.h>
57 LOG_MODULE_REGISTER(bt_controller, CONFIG_LOG_DEFAULT_LEVEL);
58
59 //*****************************************************************************
60 //
61 // Timing and configuration.
62 //
63 //*****************************************************************************
64 #define AM_DEVICES_COOPER_SBL_SEND_WAIT_TIMEOUT K_MSEC(1000)
65
66 //*****************************************************************************
67 //
68 // Global variables.
69 //
70 //*****************************************************************************
71 uint8_t am_devices_cooper_nvds[HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH] =
72 {
73 NVDS_PARAMETER_MAGIC_NUMBER,
74 NVDS_PARAMETER_SLEEP_ALGO_DUR,
75 NVDS_PARAMETER_LPCLK_DRIFT,
76 NVDS_PARAMETER_EXT_WAKEUP_TIME,
77 NVDS_PARAMETER_OSC_WAKEUP_TIME
78 };
79
80 //
81 //!
82 //
83 static am_devices_cooper_sbl_update_state_t gsSblUpdateState;
84
85 //
86 //!
87 //
88 static am_devices_cooper_sbl_update_data_t g_sFwImage =
89 {
90 0,
91 0,
92 AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_FW,
93 0
94 };
95
96 //
97 //!
98 //
99 static am_devices_cooper_sbl_update_data_t g_sInfo0PatchImage =
100 {
101 0,
102 sizeof(am_sbl_info0_patch_blob_t),
103 AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_INFO_0,
104 0
105 };
106
107 //
108 //!
109 //
110 static am_devices_cooper_sbl_update_data_t g_sInfo1PatchImage =
111 {
112 0,
113 0,
114 AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_INFO_1,
115 0
116 };
117
118 //
119 //! Cooper callback
120 //
121 static am_devices_cooper_callback_t g_CooperCb;
122
123 //
124 //! Semaphore to control the SBL packet sending
125 //
126 static K_SEM_DEFINE(sem_sbl_send, 0, 1);
127
128 //
129 //! Cooper initialization state
130 //
131 static uint32_t g_CooperInitState = 0;
132
133 //*****************************************************************************
134 //
135 // Initialize the BLE controller driver.
136 //
137 //*****************************************************************************
am_devices_cooper_init(am_devices_cooper_callback_t * cb)138 uint32_t am_devices_cooper_init(am_devices_cooper_callback_t* cb)
139 {
140 uint32_t ui32Status;
141 am_devices_cooper_set_initialize_state(AM_DEVICES_COOPER_STATE_STARTUP);
142 am_devices_cooper_image_update_init();
143
144 if ((!cb) || (!cb->write) || (!cb->reset))
145 {
146 return AM_DEVICES_COOPER_STATUS_ERROR;
147 }
148
149 // Register the callback functions
150 g_CooperCb.write = cb->write;
151 g_CooperCb.reset = cb->reset;
152
153 // Start the BLE controller firmware update machine
154 ui32Status = am_devices_cooper_update_image();
155 while ((ui32Status != AM_DEVICES_COOPER_SBL_STATUS_OK) &&
156 (ui32Status != AM_DEVICES_COOPER_SBL_STATUS_FAIL))
157 {
158 if (k_sem_take(&sem_sbl_send, AM_DEVICES_COOPER_SBL_SEND_WAIT_TIMEOUT) == 0)
159 {
160 ui32Status = am_devices_cooper_update_image();
161 }
162 else
163 {
164 return AM_DEVICES_COOPER_STATUS_TIMEOUT;
165 }
166
167 }
168
169 return AM_DEVICES_COOPER_STATUS_SUCCESS;
170 }
171
172 //*****************************************************************************
173 //
174 // Reset BLE Controller.
175 //
176 //*****************************************************************************
177 void
am_devices_cooper_reset(void)178 am_devices_cooper_reset(void)
179 {
180 g_CooperCb.reset();
181 }
182
183 //*****************************************************************************
184 //
185 // Receive a packet from the Cooper SBL.
186 //
187 //*****************************************************************************
am_devices_cooper_handshake_recv(uint8_t * pBuf,uint16_t len)188 void am_devices_cooper_handshake_recv(uint8_t* pBuf, uint16_t len)
189 {
190 am_sbl_host_msg_hdr_t* msg;
191 uint32_t crc32;
192
193 // Verify the received data CRC
194 msg = (am_sbl_host_msg_hdr_t*)pBuf;
195 am_hal_crc32((uint32_t)&msg->msgType, msg->msgLength - sizeof(uint32_t), &crc32);
196
197 gsSblUpdateState.pWorkBuf = (uint32_t*)msg;
198 gsSblUpdateState.bRxCrcCheckPass = (crc32 == msg->msgCrc);
199 gsSblUpdateState.ui32RxPacketLength = len;
200
201 k_sem_give(&sem_sbl_send);
202 }
203
204 //*****************************************************************************
205 //
206 // Send a "HELLO" packet.
207 //
208 //*****************************************************************************
send_hello(void)209 static void send_hello(void)
210 {
211 am_sbl_host_msg_hdr_t msg;
212 msg.msgType = AM_SBL_HOST_MSG_HELLO;
213 msg.msgLength = sizeof(am_sbl_host_msg_hdr_t);
214 //
215 // Compute CRC
216 //
217 am_hal_crc32((uint32_t)&msg.msgType, msg.msgLength - sizeof(uint32_t), &msg.msgCrc);
218 g_CooperCb.write((uint8_t*)&msg, sizeof(msg));
219 }
220
221 //*****************************************************************************
222 //
223 // Send a "UPDATE" packet.
224 //
225 //*****************************************************************************
send_update(uint32_t imgBlobSize)226 static void send_update(uint32_t imgBlobSize)
227 {
228 am_sbl_host_msg_update_t msg;
229 msg.msgHdr.msgType = AM_SBL_HOST_MSG_UPDATE;
230 msg.msgHdr.msgLength = sizeof(am_sbl_host_msg_update_t);
231 msg.imageSize = imgBlobSize;
232 // Check if we are downloading a newer FW versiion
233 if ((gsSblUpdateState.ui32CooperFWImageVersion < g_sFwImage.version)
234 || (gsSblUpdateState.ui32CooperVerRollBackConfig & 0x00000001))
235 {
236 msg.versionNumber = g_sFwImage.version;
237 }
238 else
239 {
240 msg.versionNumber = gsSblUpdateState.ui32CooperFWImageVersion;
241 }
242 msg.NumPackets = gsSblUpdateState.ui32TotalPackets + 1; // One addition packet as header will be a seperate packet
243
244 // imageSize will be zero if Apollo4 has no available image/patch for Cooper to load
245 // set maxPacketSize to invalid parameter to let Cooper to reply NACK and clear signature
246 if ( msg.imageSize == 0 )
247 {
248 msg.maxPacketSize = AM_DEVICES_COOPER_SBL_UPADTE_INVALID_PSI_PKT_SIZE;
249 }
250 else
251 {
252 msg.maxPacketSize = AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
253 }
254 //
255 // Compute CRC
256 //
257 am_hal_crc32((uint32_t)&msg.msgHdr.msgType, msg.msgHdr.msgLength - sizeof(uint32_t), &msg.msgHdr.msgCrc);
258 g_CooperCb.write((uint8_t*)&msg, sizeof(msg));
259 }
260
261 //*****************************************************************************
262 //
263 // Send a "Data" packet.
264 //
265 //*****************************************************************************
send_data(uint32_t address,uint32_t size,uint32_t pktNumber)266 static void send_data(uint32_t address, uint32_t size, uint32_t pktNumber)
267 {
268 // reuse same buffer for receiving
269 am_sbl_host_msg_data_t* msg = (am_sbl_host_msg_data_t*)gsSblUpdateState.pWorkBuf;
270 msg->msgHdr.msgType = AM_SBL_HOST_MSG_DATA;
271 msg->msgHdr.msgLength = sizeof(am_sbl_host_msg_data_t) + size;
272 msg->packetNumber = pktNumber;
273 memcpy((uint8_t*)msg->data, (uint8_t*)address, size);
274 //
275 // Compute CRC
276 //
277 am_hal_crc32((uint32_t) & (msg->msgHdr.msgType), msg->msgHdr.msgLength - sizeof(uint32_t), &msg->msgHdr.msgCrc);
278 g_CooperCb.write((uint8_t*)msg, (sizeof(am_sbl_host_msg_data_t) + size));
279 }
280
281 //*****************************************************************************
282 //
283 // Send a "Reset" packet.
284 //
285 //*****************************************************************************
send_reset(void)286 void send_reset(void)
287 {
288 am_sbl_host_msg_reset_t msg;
289 msg.msgHdr.msgType = AM_SBL_HOST_MSG_RESET;
290 msg.msgHdr.msgLength = sizeof(am_sbl_host_msg_reset_t);
291 //
292 // Compute CRC
293 //
294 am_hal_crc32((uint32_t)&msg.msgHdr.msgType, msg.msgHdr.msgLength - sizeof(uint32_t), &msg.msgHdr.msgCrc);
295 g_CooperCb.write((uint8_t*)&msg, sizeof(msg));
296 }
297
298 //*****************************************************************************
299 //
300 // Send a "FW Continue packet.
301 //
302 //*****************************************************************************
send_fwContinue(void)303 static void send_fwContinue(void)
304 {
305 am_sbl_host_msg_fw_continue_t msg;
306 msg.msgHdr.msgType = AM_SBL_HOST_MSG_FW_CONTINUE;
307 msg.msgHdr.msgLength = sizeof(am_sbl_host_msg_fw_continue_t);
308 //
309 // Compute CRC
310 //
311 am_hal_crc32((uint32_t)&msg.msgHdr.msgType, msg.msgHdr.msgLength - sizeof(uint32_t), &msg.msgHdr.msgCrc);
312 g_CooperCb.write((uint8_t*)&msg, sizeof(msg));
313 }
314
315 //*****************************************************************************
316 //
317 // Update the state machine based on the image to download
318 //
319 //*****************************************************************************
am_devices_cooper_sbl_update_state_data(uint32_t ui32updateType)320 static bool am_devices_cooper_sbl_update_state_data(uint32_t ui32updateType)
321 {
322 // Pointer to the data to be updated
323 am_devices_cooper_sbl_update_data_t* p_sUpdateImageData = NULL;
324 if ( ui32updateType == AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_FW )
325 {
326 p_sUpdateImageData = &g_sFwImage;
327 }
328 else if ( ui32updateType == AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_INFO_0 )
329 {
330 p_sUpdateImageData = &g_sInfo0PatchImage;
331 }
332 else if ( ui32updateType == AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_INFO_1 )
333 {
334 p_sUpdateImageData = &g_sInfo1PatchImage;
335 }
336 else
337 {
338 return false;
339 }
340 // Check if the data is valid
341 if ( (p_sUpdateImageData != NULL) &&
342 (p_sUpdateImageData->pImageAddress != 0 ) &&
343 (p_sUpdateImageData->imageSize != 0 ) &&
344 (p_sUpdateImageData->imageType == ui32updateType) )
345 {
346 // Load the INFO 0 Patch address
347 gsSblUpdateState.pImageBuf = p_sUpdateImageData->pImageAddress;
348 // Image size
349 gsSblUpdateState.ui32ImageSize = p_sUpdateImageData->imageSize;
350 // image type
351 gsSblUpdateState.ui32ImageType = p_sUpdateImageData->imageType;
352 // Get the size of the data without headers
353 gsSblUpdateState.ui32DataSize = gsSblUpdateState.ui32ImageSize - AM_DEVICES_COOPER_SBL_UPADTE_IMAGE_HDR_SIZE;
354 // Get the start address of the data without headers
355 gsSblUpdateState.pDataBuf = gsSblUpdateState.pImageBuf + AM_DEVICES_COOPER_SBL_UPADTE_IMAGE_HDR_SIZE;
356 // Calculate number of packets
357 gsSblUpdateState.ui32TotalPackets = gsSblUpdateState.ui32DataSize / AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
358 if ( (gsSblUpdateState.ui32DataSize % AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE) != 0 )
359 {
360 gsSblUpdateState.ui32TotalPackets++;
361 }
362 gsSblUpdateState.ui32PacketNumber = 0;
363 return true;
364 }
365
366 return false;
367 }
368 //*****************************************************************************
369 //
370 // Initialize the Image Update state machine
371 //
372 //*****************************************************************************
am_devices_cooper_image_update_init(void)373 void am_devices_cooper_image_update_init(void)
374 {
375 // Initialize state machine
376 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_INIT;
377 // Load the image address
378 gsSblUpdateState.pImageBuf = NULL;
379 // Image size
380 gsSblUpdateState.ui32ImageSize = 0;
381 // image type
382 gsSblUpdateState.ui32ImageType = AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_NONE;
383 // Get the size of the data without headers
384 gsSblUpdateState.ui32DataSize = 0;
385 // Get the start address of the data without headers
386 gsSblUpdateState.pDataBuf = NULL;
387 // Calculate number of packets
388 gsSblUpdateState.ui32TotalPackets = 0;
389 // Initialize Packet number in progress
390 gsSblUpdateState.ui32PacketNumber = 0;
391 // Initialize the processing buffer
392 gsSblUpdateState.pWorkBuf = NULL;
393 // Initialize the RX CRC check result
394 gsSblUpdateState.bRxCrcCheckPass = false;
395 // Initialzie the length of receive packet
396 gsSblUpdateState.ui32RxPacketLength = 0;
397 }
398
399 //*****************************************************************************
400 //
401 // @breif Update Image
402 // @return uint32_t
403 //
404 //*****************************************************************************
am_devices_cooper_update_image(void)405 uint32_t am_devices_cooper_update_image(void)
406 {
407 uint32_t ui32dataPktSize = 0;
408 uint32_t ui32Size = gsSblUpdateState.ui32RxPacketLength;
409 uint32_t ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_INIT;
410 am_sbl_host_msg_status_t* psStatusMsg;
411 am_sbl_host_msg_ack_nack_t* psAckMsg;
412 switch (gsSblUpdateState.ui32SblUpdateState)
413 {
414 case AM_DEVICES_COOPER_SBL_UPDATE_STATE_INIT:
415 //
416 // Send the "HELLO" message to connect to the interface.
417 //
418 send_hello();
419 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_HELLO;
420 // Tell application that we are not done with SBL
421 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
422 break;
423 case AM_DEVICES_COOPER_SBL_UPDATE_STATE_HELLO:
424 // Read the "STATUS" response from the IOS and check for CRC Error
425 if ( gsSblUpdateState.bRxCrcCheckPass == false )
426 {
427 // Increment the Error Counter
428 gsSblUpdateState.ui32ErrorCounter++;
429 // Check if the Error has happened more than the limit
430 if ( gsSblUpdateState.ui32ErrorCounter > AM_DEVICES_COOPER_SBL_MAX_COMM_ERR_COUNT )
431 {
432 // Return fail
433 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
434 }
435 else
436 {
437 // Resend the previous message
438 send_hello();
439 // Tell application that we are not done with SBL
440 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
441 }
442 }
443 else
444 {
445 // No CRC error and if there was one, then reset the error counter
446 if ( gsSblUpdateState.ui32ErrorCounter )
447 {
448 gsSblUpdateState.ui32ErrorCounter = 0;
449 }
450 // Check the status
451 psStatusMsg = (am_sbl_host_msg_status_t*) (gsSblUpdateState.pWorkBuf);
452 gsSblUpdateState.ui32CooperSblStatus = psStatusMsg->bootStatus;
453 // Get the Cooper FW version
454 if ( psStatusMsg->versionNumber == AM_DEVICES_COOPER_SBL_DEFAULT_FW_VERSION )
455 {
456 gsSblUpdateState.ui32CooperFWImageVersion = 0;
457 }
458 else
459 {
460 gsSblUpdateState.ui32CooperFWImageVersion = psStatusMsg->versionNumber;
461 }
462 LOG_INF("BLE Controller Info:");
463 /*
464 * Before Cooper firmware version 1.19 (0x00000113), only the lower 16-bit of 32-bit Cooper firmware version
465 * word was used to identify Cooper firmware. It was limited to distinguish the difference of testing binaries.
466 * To restructure the Cooper firmware version to a.b.c.d from a.b may solve this problem.
467 * The higher 16-bit is used to identify the major and minor version of based release firmware.
468 * The lower 16-bit is used to identify the version for testing before next release.
469 * Originally the code only prints the lower 16-bit of FW version, need to print all the bytes
470 * based on new structure of firmware version now.
471 */
472 if ((psStatusMsg->versionNumber & 0xFFFF0000) == 0)
473 {
474 LOG_INF("\tFW Ver: %d.%d", (psStatusMsg->versionNumber & 0xF00) >> 8, psStatusMsg->versionNumber & 0xFF);
475 }
476 else
477 {
478 LOG_INF("\tFW Ver: %d.%d.%d.%d", (psStatusMsg->versionNumber & 0xFF000000) >> 24, (psStatusMsg->versionNumber & 0xFF0000) >> 16,
479 (psStatusMsg->versionNumber & 0xFF00) >> 8, psStatusMsg->versionNumber & 0xFF);
480 }
481 if (ui32Size == sizeof(am_sbl_host_msg_status_t))
482 {
483 // Get the version rollback configuration
484 gsSblUpdateState.ui32CooperVerRollBackConfig = psStatusMsg->verRollBackStatus;
485 if ( psStatusMsg->verRollBackStatus == AM_DEVICES_COOPER_SBL_STAT_VER_ROLL_BACK_EN )
486 {
487 LOG_DBG("Version RollBack Enabled ");
488 }
489 else if ( psStatusMsg->verRollBackStatus == AM_DEVICES_COOPER_SBL_STAT_VER_ROLL_BACK_DBL )
490 {
491 LOG_DBG("Version RollBack Disabled ");
492 }
493 else
494 {
495 LOG_DBG("Version RollBack Config invalid !!! ");
496 }
497 LOG_INF("\tChip ID0: 0x%x", psStatusMsg->copperChipIdWord0);
498 LOG_INF("\tChip ID1: 0x%x", psStatusMsg->copperChipIdWord1);
499
500 gsSblUpdateState.ui32copperChipIdWord0 = psStatusMsg->copperChipIdWord0;
501 gsSblUpdateState.ui32copperChipIdWord1 = psStatusMsg->copperChipIdWord1;
502
503 }
504 else
505 {
506 gsSblUpdateState.ui32CooperVerRollBackConfig = 0x0;
507 }
508 LOG_DBG("bootStatus 0x%x", psStatusMsg->bootStatus);
509
510 // check if the Boot Status is success
511 if ( psStatusMsg->bootStatus == AM_DEVICES_COOPER_SBL_STAT_RESP_SUCCESS )
512 {
513 // Check if we have some FW available
514 if ( am_devices_cooper_sbl_update_state_data(AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_FW) == true )
515 {
516 // Check if we have a newer FW version
517 if ( psStatusMsg->versionNumber < g_sFwImage.version )
518 {
519 // We have newer FW available, Letus upgrade
520 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_FW;
521 if ((g_sFwImage.version & 0xFFFF0000) == 0)
522 {
523 LOG_INF("Received new BLE Controller FW version = %d.%d Going for upgrade", (g_sFwImage.version & 0xF00) >> 8, g_sFwImage.version & 0xFF);
524 }
525 else
526 {
527 LOG_INF("Received new BLE Controller FW version = %d.%d.%d.%d Going for upgrade", (g_sFwImage.version & 0xFF000000) >> 24, (g_sFwImage.version & 0xFF0000) >> 16,
528 (g_sFwImage.version & 0xFF00) >> 8, g_sFwImage.version & 0xFF);
529 }
530 }
531 }
532 // If we don't have any FW or any newer FW then continue with the current FW in Cooper
533 if ( ui32Ret != AM_DEVICES_COOPER_SBL_STATUS_UPDATE_FW )
534 {
535 // We don't have any other FW, so continue with one already there is Cooper device
536 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_IMAGE_OK;
537 // Not done yet
538 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
539 LOG_INF("No new image to upgrade");
540 // Send the command to continue to FW
541 send_fwContinue();
542 LOG_INF("BLE Controller FW Auth Passed, Continue with FW");
543 }
544 }
545 else if ( psStatusMsg->bootStatus == AM_DEVICES_COOPER_SBL_STAT_RESP_FW_UPDATE_REQ )
546 {
547 LOG_INF("BLE Controller Requires FW");
548 if ( am_devices_cooper_sbl_update_state_data(AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_FW) == true )
549 {
550 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_FW;
551 }
552 else
553 {
554 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_IMAGE_FAIL;
555 }
556 }
557 else if ( psStatusMsg->bootStatus == AM_DEVICES_COOPER_SBL_STAT_RESP_INFO0_UPDATE_REQ )
558 {
559 LOG_INF("BLE Controller Requires INFO 0");
560 if ( am_devices_cooper_sbl_update_state_data(AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_INFO_0) == true )
561 {
562 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_INFO_0;
563 }
564 else
565 {
566 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_IMAGE_FAIL;
567 }
568 }
569 else if ( psStatusMsg->bootStatus == AM_DEVICES_COOPER_SBL_STAT_RESP_INFO1_UPDATE_REQ )
570 {
571 LOG_INF("BLE Controller Requires INFO 1");
572 if ( am_devices_cooper_sbl_update_state_data(AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_INFO_1) == true )
573 {
574 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_INFO_1;
575 }
576 else
577 {
578 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_UPDATE_IMAGE_FAIL;
579 }
580 }
581 else
582 {
583 LOG_ERR("BLE Controller Wrong Response");
584 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
585 }
586 }
587 if ( (ui32Ret == AM_DEVICES_COOPER_SBL_STATUS_OK) || (ui32Ret == AM_DEVICES_COOPER_SBL_STATUS_FAIL) ||
588 (gsSblUpdateState.ui32SblUpdateState == AM_DEVICES_COOPER_SBL_UPDATE_STATE_IMAGE_OK) )
589 {
590 // Do nothing
591 }
592 else
593 {
594 // for the case ui32Ret == AM_DEVICES_COOPER_SBL_STATUS_UPDATE_IMAGE_FAIL,
595 // it indicates Cooper has available FW/Info0/Info1 signature and requests update,
596 // but Apollo4 does not have such image/patch at this moment, gsSblUpdateState.ui32ImageSize should be zero.
597 // Need to send_update with invalid parameter to let Cooper reply NACK and clear signature
598
599 // Update the state machine
600 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_UPDATE;
601 // Send the update message
602 send_update(gsSblUpdateState.ui32ImageSize);
603 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
604 }
605 break;
606 case AM_DEVICES_COOPER_SBL_UPDATE_STATE_UPDATE:
607 // Read the "ACK/NACK" response from the IOS and check for CRC Error
608 if ( gsSblUpdateState.bRxCrcCheckPass == false )
609 {
610 // Increment the Error Counter
611 gsSblUpdateState.ui32ErrorCounter++;
612 // Check if the Error has happened more than the limit
613 if ( gsSblUpdateState.ui32ErrorCounter > AM_DEVICES_COOPER_SBL_MAX_COMM_ERR_COUNT )
614 {
615 // Return fail
616 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
617 }
618 else
619 {
620 // Resend the previous message
621 send_update(gsSblUpdateState.ui32ImageSize);
622 // Tell application that we are not done with SBL
623 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
624 }
625 }
626 else
627 {
628 // No CRC error and if there was one, then reset the error counter
629 if ( gsSblUpdateState.ui32ErrorCounter )
630 {
631 gsSblUpdateState.ui32ErrorCounter = 0;
632 }
633 // Get the response status
634 psAckMsg = (am_sbl_host_msg_ack_nack_t*)(gsSblUpdateState.pWorkBuf);
635 // Process the response
636 if ( (psAckMsg->msgHdr.msgType == AM_SBL_HOST_MSG_ACK) && (NULL != gsSblUpdateState.pImageBuf))
637 {
638 // Save the status
639 gsSblUpdateState.ui32CooperSblStatus = psAckMsg->status;
640 // Change the state
641 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_DATA;
642 // Send the Encrypted image header - first 64 bytes
643 send_data((uint32_t)gsSblUpdateState.pImageBuf,
644 AM_DEVICES_COOPER_SBL_UPADTE_IMAGE_HDR_SIZE, gsSblUpdateState.ui32PacketNumber);
645 LOG_INF("BLE controller upgrade in progress, wait...");
646 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
647 }
648 else if ( (psAckMsg->msgHdr.msgType == AM_SBL_HOST_MSG_NACK) && (psAckMsg->status == AM_DEVICES_COOPER_SBL_ACK_RESP_INVALID_PARAM) )
649 {
650 LOG_INF("Clear Cooper Signature, reset Cooper and talk with SBL again");
651 // Add some delay for Cooper SBL to clear signature
652 k_sleep(K_MSEC(1200));
653 am_devices_cooper_reset();
654 gsSblUpdateState.pImageBuf = NULL;
655 gsSblUpdateState.ui32ImageSize = 0;
656 gsSblUpdateState.ui32ImageType = AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_NONE;
657 gsSblUpdateState.ui32DataSize = 0;
658 gsSblUpdateState.pDataBuf = NULL;
659 gsSblUpdateState.ui32TotalPackets = 0;
660 gsSblUpdateState.ui32PacketNumber = 0;
661
662 // Send the "HELLO" message to connect to the interface.
663 send_hello();
664 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_HELLO;
665 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
666 }
667 else
668 {
669 LOG_ERR("Update Failed !!!");
670 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
671 }
672 }
673 break;
674 case AM_DEVICES_COOPER_SBL_UPDATE_STATE_DATA:
675 // Read the "ACK/NACK" response from the IOS.
676 if ( gsSblUpdateState.bRxCrcCheckPass == false )
677 {
678 // Increment the Error Counter
679 gsSblUpdateState.ui32ErrorCounter++;
680 // Check if the Error has happened more than the limit
681 if ( gsSblUpdateState.ui32ErrorCounter > AM_DEVICES_COOPER_SBL_MAX_COMM_ERR_COUNT )
682 {
683 // Return fail
684 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
685 }
686 else
687 {
688 // Resend the previous message
689 if ( gsSblUpdateState.ui32PacketNumber == 0 )
690 {
691 // Send the Encrypted image header - first 64 bytes
692 send_data((uint32_t)gsSblUpdateState.pImageBuf,
693 AM_DEVICES_COOPER_SBL_UPADTE_IMAGE_HDR_SIZE, gsSblUpdateState.ui32PacketNumber);
694 }
695 else
696 {
697 //Check if this is the last packet - Increase by one as we have already decremented after TX
698 if ( (gsSblUpdateState.ui32TotalPackets + 1) == 1 )
699 {
700 // Get the size of the leftover data
701 ui32dataPktSize = gsSblUpdateState.ui32DataSize % AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
702 if (ui32dataPktSize == 0)
703 {
704 ui32dataPktSize = AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
705 }
706 }
707 else
708 {
709 ui32dataPktSize = AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
710 }
711 // Resend the same packet - Need to decrement the packet numbers as those are already incremented
712 send_data((uint32_t) gsSblUpdateState.pDataBuf + ( (gsSblUpdateState.ui32PacketNumber - 1) * AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE),
713 ui32dataPktSize, gsSblUpdateState.ui32PacketNumber);
714 }
715 // Tell application that we are not done with SBL
716 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
717 }
718 }
719 else
720 {
721 // No CRC error and if there was one, then reset the error counter
722 if ( gsSblUpdateState.ui32ErrorCounter )
723 {
724 gsSblUpdateState.ui32ErrorCounter = 0;
725 }
726 // Get the response status
727 psAckMsg = (am_sbl_host_msg_ack_nack_t*)(gsSblUpdateState.pWorkBuf);
728 // Save the status
729 gsSblUpdateState.ui32CooperSblStatus = psAckMsg->status;
730 if ( (psAckMsg->srcMsgType == AM_SBL_HOST_MSG_DATA ) || (psAckMsg->srcMsgType == AM_SBL_HOST_MSG_UPDATE_STATUS) )
731 {
732 if ( (psAckMsg->status == AM_DEVICES_COOPER_SBL_ACK_RESP_SUCCESS) || (psAckMsg->status == AM_DEVICES_COOPER_SBL_ACK_RESP_SEQ) )
733 {
734 if ( gsSblUpdateState.ui32TotalPackets > 0 )
735 {
736 //Check if this is the last packet
737 if ( gsSblUpdateState.ui32TotalPackets == 1 )
738 {
739 // Get the size of the left over data
740 ui32dataPktSize = gsSblUpdateState.ui32DataSize % AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
741 if (ui32dataPktSize == 0)
742 {
743 ui32dataPktSize = AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
744 }
745 }
746 else
747 {
748 ui32dataPktSize = AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE;
749 }
750 send_data((uint32_t) gsSblUpdateState.pDataBuf + (gsSblUpdateState.ui32PacketNumber * AM_DEVICES_COOPER_SBL_UPADTE_MAX_SPI_PKT_SIZE),
751 ui32dataPktSize, gsSblUpdateState.ui32PacketNumber + 1);
752 gsSblUpdateState.ui32TotalPackets--;
753 // increment the packet number as we have already sent the header
754 gsSblUpdateState.ui32PacketNumber++;
755 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
756 }
757 else
758 {
759 if ( psAckMsg->status == AM_DEVICES_COOPER_SBL_ACK_RESP_SUCCESS )
760 {
761 // If FW is updated successfuly, then jump to BLE image
762 if ( gsSblUpdateState.ui32ImageType == AM_DEVICES_COOPER_SBL_UPDATE_IMAGE_TYPE_FW )
763 {
764 gsSblUpdateState.ui32SblUpdateState = AM_DEVICES_COOPER_SBL_UPDATE_STATE_IMAGE_OK;
765 gsSblUpdateState.ui32CooperFWImageVersion = g_sFwImage.version;
766 // Not done yet
767 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
768 // Send the command to continue to FW
769 send_fwContinue();
770 // If INFO 0 or INFO 1 is updated successfully, the apply send reset
771 }
772 else
773 {
774 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_OK;
775 }
776 }
777 else
778 {
779 LOG_ERR("Update fails status = 0x%x", psAckMsg->status);
780 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
781 }
782 }
783 }
784 else
785 {
786 LOG_ERR("Update fails status = 0x%x", psAckMsg->status);
787 // We have received NACK
788 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
789 }
790 }
791 else
792 {
793 // Wrong Response type
794 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
795 }
796 }
797 break;
798 case AM_DEVICES_COOPER_SBL_UPDATE_STATE_IMAGE_OK:
799 {
800 // Read the "ACK/NACK" response from the IOS and check for CRC Error
801 if ( gsSblUpdateState.bRxCrcCheckPass == false )
802 {
803 // Increment the Error Counter
804 gsSblUpdateState.ui32ErrorCounter++;
805 // Check if the Error has happened more than the limit
806 if ( gsSblUpdateState.ui32ErrorCounter > AM_DEVICES_COOPER_SBL_MAX_COMM_ERR_COUNT )
807 {
808 // Return fail
809 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
810 }
811 else
812 {
813 // Resend the previous message
814 send_fwContinue();
815 // Tell application that we are not done with SBL
816 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_IN_PROGRESS;
817 }
818 }
819 else
820 {
821 // No CRC error and if there was one, then reset the error counter
822 if ( gsSblUpdateState.ui32ErrorCounter )
823 {
824 gsSblUpdateState.ui32ErrorCounter = 0;
825 }
826 }
827 // Get the response status
828 psAckMsg = (am_sbl_host_msg_ack_nack_t*)(gsSblUpdateState.pWorkBuf);
829 // Save the status
830 gsSblUpdateState.ui32CooperSblStatus = psAckMsg->status;
831 if ( psAckMsg->status == AM_DEVICES_COOPER_SBL_ACK_RESP_SUCCESS )
832 {
833 // FW has gone to BLE, end the SBL driver state machine
834 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_OK;
835 }
836 else
837 {
838 ui32Ret = AM_DEVICES_COOPER_SBL_STATUS_FAIL;
839 }
840 }
841 break;
842 default:
843 // Bad state, update the state machine
844 break;
845 }
846 return ui32Ret;
847 }
848
849 //*****************************************************************************
850 //
851 // Get cooper firmware image from local binary
852 //
853 //*****************************************************************************
am_devices_cooper_get_FwImage(am_devices_cooper_sbl_update_data_t * pFwImage)854 bool am_devices_cooper_get_FwImage(am_devices_cooper_sbl_update_data_t *pFwImage )
855 {
856 if (pFwImage != NULL)
857 {
858 memcpy(&g_sFwImage, pFwImage, sizeof(am_devices_cooper_sbl_update_data_t));
859 // Get version from the firmware image
860 g_sFwImage.version = (pFwImage->pImageAddress[27] << 24) | (pFwImage->pImageAddress[26] << 16) | (pFwImage->pImageAddress[25] << 8) | (pFwImage->pImageAddress[24]);
861 }
862
863 return (pFwImage != NULL);
864 }
865
866 //*****************************************************************************
867 //
868 // Get cooper info1 image from local binary
869 //
870 //*****************************************************************************
am_devices_cooper_get_info1_patch(am_devices_cooper_sbl_update_data_t * pInfo1Image)871 bool am_devices_cooper_get_info1_patch(am_devices_cooper_sbl_update_data_t *pInfo1Image)
872 {
873 if (pInfo1Image != NULL)
874 {
875 memcpy(&g_sInfo1PatchImage, pInfo1Image, sizeof(am_devices_cooper_sbl_update_data_t));
876 }
877
878 return (pInfo1Image != NULL);
879 }
880
881 //*****************************************************************************
882 //
883 // Get cooper info0 image from local binary
884 //
885 //*****************************************************************************
am_devices_cooper_get_info0_patch(am_devices_cooper_sbl_update_data_t * pInfo0Image)886 bool am_devices_cooper_get_info0_patch(am_devices_cooper_sbl_update_data_t *pInfo0Image)
887 {
888 if (pInfo0Image != NULL)
889 {
890 memcpy(&g_sInfo0PatchImage, pInfo0Image, sizeof(am_devices_cooper_sbl_update_data_t));
891 }
892
893 return (pInfo0Image != NULL);
894 }
895
896
897 //*****************************************************************************
898 //
899 // Reset the BLE controller and check if there's request to update
900 //
901 //*****************************************************************************
am_devices_cooper_reset_with_sbl_check(void)902 uint32_t am_devices_cooper_reset_with_sbl_check(void)
903 {
904 uint32_t u32SblStatus = 0;
905 am_devices_cooper_reset();
906 am_devices_cooper_set_initialize_state(AM_DEVICES_COOPER_STATE_STARTUP);
907 am_devices_cooper_image_update_init();
908 u32SblStatus = AM_DEVICES_COOPER_SBL_STATUS_INIT;
909 u32SblStatus = am_devices_cooper_update_image();
910 while ((u32SblStatus != AM_DEVICES_COOPER_SBL_STATUS_OK) &&
911 (u32SblStatus != AM_DEVICES_COOPER_SBL_STATUS_FAIL))
912 {
913 if (k_sem_take(&sem_sbl_send, AM_DEVICES_COOPER_SBL_SEND_WAIT_TIMEOUT) == 0)
914 {
915 u32SblStatus = am_devices_cooper_update_image();
916 }
917 else
918 {
919 return AM_DEVICES_COOPER_STATUS_TIMEOUT;
920 }
921
922 }
923
924 if (u32SblStatus == AM_DEVICES_COOPER_SBL_STATUS_OK)
925 {
926 // need to wait a bit to jump from SBL to Cooper application firmware
927 k_sleep(K_MSEC(10));
928 LOG_INF("Update Done");
929 return AM_DEVICES_COOPER_STATUS_SUCCESS;
930 }
931 else
932 {
933 LOG_ERR("BLE Controller SBL Error 0x%x", u32SblStatus);
934 return u32SblStatus;
935 }
936 }
937
938 //*****************************************************************************
939 //
940 // Get the Cooper initialization state
941 //
942 //*****************************************************************************
am_devices_cooper_get_initialize_state(void)943 uint32_t am_devices_cooper_get_initialize_state(void)
944 {
945 return g_CooperInitState;
946 }
947
948 //*****************************************************************************
949 //
950 // Set the Cooper initialization state
951 //
952 //*****************************************************************************
am_devices_cooper_set_initialize_state(uint32_t state)953 void am_devices_cooper_set_initialize_state(uint32_t state)
954 {
955 g_CooperInitState = state;
956 }
957
958 //*****************************************************************************
959 //
960 // End Doxygen group.
961 //! @}
962 //
963 //*****************************************************************************
964