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