1 /**
2  * @file flc_common.c
3  * @brief      Common functions for the flash controller drivers.
4  * @details    This driver can be used to operate on the embedded flash memory.
5  */
6 /******************************************************************************
7  *
8  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
9  * Analog Devices, Inc.),
10  * Copyright (C) 2023-2024 Analog Devices, Inc.
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *     http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  *
24  ******************************************************************************/
25 
26 /* **** Includes **** */
27 #include <string.h>
28 #include "mxc_device.h"
29 #include "mxc_assert.h"
30 #include "mxc_sys.h"
31 #include "flc.h"
32 #include "flc_common.h"
33 #include "stdlib.h"
34 
35 //******************************************************************************
36 #if IAR_PRAGMAS
37 #pragma section = ".flashprog"
38 #else
39 __attribute__((section(".flashprog")))
40 #endif
41 // Length is number of 32-bit words
MXC_FLC_Com_VerifyData(uint32_t address,uint32_t length,uint32_t * data)42 int MXC_FLC_Com_VerifyData(uint32_t address, uint32_t length, uint32_t *data)
43 {
44     volatile uint32_t *ptr;
45 
46     for (ptr = (uint32_t *)address; ptr < (((uint32_t *)(address)) + length); ptr++, data++) {
47         if (*ptr != *data) {
48             return E_BAD_STATE;
49         }
50     }
51 
52     return E_NO_ERROR;
53 }
54 
55 //******************************************************************************
56 #if IAR_PRAGMAS
57 #pragma section = ".flashprog"
58 #else
59 __attribute__((section(".flashprog")))
60 #endif
61 // make sure to disable ICC with ICC_Disable(); before Running this function
MXC_FLC_Com_Write(uint32_t address,uint32_t length,uint32_t * buffer)62 int MXC_FLC_Com_Write(uint32_t address, uint32_t length, uint32_t *buffer)
63 {
64     int err;
65     uint32_t bytes_written;
66 
67     uint32_t current_data_32;
68     uint8_t *current_data = (uint8_t *)&current_data_32;
69     uint8_t *buffer8 = (uint8_t *)buffer;
70 
71     // Align the address to a word boundary and read/write if we have to
72     if (address & 0x3) {
73         // Figure out how many bytes we have to write to round up the address
74         bytes_written = 4 - (address & 0x3);
75 
76         // Save the data currently in the flash
77         memcpy(current_data, (void *)(address & (~0x3)), 4);
78 
79         // Modify current_data to insert the data from buffer
80         memcpy(&current_data[4 - bytes_written], buffer8, bytes_written);
81 
82         // Write the modified data
83         if ((err = MXC_FLC_Write32(address - (address % 4), current_data_32)) != E_NO_ERROR) {
84             return err;
85         }
86 
87         address += bytes_written;
88         length -= bytes_written;
89         buffer8 += bytes_written;
90     }
91 
92     // Align the address to a 4-word (128bit) boundary
93     while ((length >= 4) && ((address & 0xF) != 0)) {
94         memcpy(current_data, buffer8, 4);
95         if ((err = MXC_FLC_Write32(address, current_data_32)) != E_NO_ERROR) {
96             return err;
97         }
98 
99         address += 4;
100         length -= 4;
101         buffer8 += 4;
102     }
103 
104     if (length >= 16) {
105         uint32_t buff128[4];
106         while (length >= 16) {
107             memcpy(buff128, buffer8, 16);
108             if ((err = MXC_FLC_Write128(address, buff128)) != E_NO_ERROR) {
109                 return err;
110             }
111 
112             address += 16;
113             length -= 16;
114             buffer8 += 16;
115         }
116     }
117 
118     while (length >= 4) {
119         memcpy(current_data, buffer8, 4);
120         if ((err = MXC_FLC_Write32(address, current_data_32)) != E_NO_ERROR) {
121             return err;
122         }
123 
124         address += 4;
125         length -= 4;
126         buffer8 += 4;
127     }
128 
129     if (length > 0) {
130         // Save the data currently in the flash
131         memcpy(current_data, (void *)(address), 4);
132 
133         // Modify current_data to insert the data from buffer
134         memcpy(current_data, buffer8, length);
135 
136         if ((err = MXC_FLC_Write32(address, current_data_32)) != E_NO_ERROR) {
137             return err;
138         }
139     }
140 
141     return E_NO_ERROR;
142 }
143 
144 //******************************************************************************
145 #if IAR_PRAGMAS
146 #pragma section = ".flashprog"
147 #else
148 __attribute__((section(".flashprog")))
149 #endif
MXC_FLC_Com_Read(int address,void * buffer,int len)150 void MXC_FLC_Com_Read(int address, void *buffer, int len)
151 {
152     memcpy(buffer, (void *)address, len);
153 }
154