GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nor_flash_physical_sector_allocate.c Lines: 50 67 74.6 %
Date: 2024-03-11 05:20:25 Branches: 33 44 75.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** LevelX Component                                                      */
16
/**                                                                       */
17
/**   NOR Flash                                                           */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define LX_SOURCE_CODE
23
24
25
/* Disable ThreadX error checking.  */
26
27
#ifndef LX_DISABLE_ERROR_CHECKING
28
#define LX_DISABLE_ERROR_CHECKING
29
#endif
30
31
32
/* Include necessary system files.  */
33
34
#include "lx_api.h"
35
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _lx_nor_flash_physical_sector_allocate              PORTABLE C      */
42
/*                                                           6.1.7        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    William E. Lamie, Microsoft Corporation                             */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function allocates a free physical sector for mapping to a     */
50
/*    logical sector.                                                     */
51
/*                                                                        */
52
/*  INPUT                                                                 */
53
/*                                                                        */
54
/*    nor_flash                             NOR flash instance            */
55
/*    logical_sector                        Logical sector number         */
56
/*    physical_sector_map_entry             Pointer to sector map entry   */
57
/*    physical_sector_address               Address of physical sector    */
58
/*                                                                        */
59
/*  OUTPUT                                                                */
60
/*                                                                        */
61
/*    return status                                                       */
62
/*                                                                        */
63
/*  CALLS                                                                 */
64
/*                                                                        */
65
/*    _lx_nor_flash_driver_write            Driver flash sector write     */
66
/*    _lx_nor_flash_driver_read             Driver flash sector read      */
67
/*    _lx_nor_flash_system_error            Internal system error handler */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    Internal LevelX                                                     */
72
/*                                                                        */
73
/*  RELEASE HISTORY                                                       */
74
/*                                                                        */
75
/*    DATE              NAME                      DESCRIPTION             */
76
/*                                                                        */
77
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
78
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
79
/*                                            resulting in version 6.1    */
80
/*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
81
/*                                            resulting in version 6.1.7  */
82
/*                                                                        */
83
/**************************************************************************/
84
17874
UINT  _lx_nor_flash_physical_sector_allocate(LX_NOR_FLASH *nor_flash, ULONG logical_sector, ULONG **physical_sector_map_entry, ULONG **physical_sector_address)
85
{
86
87
ULONG   search_block;
88
ULONG   *block_word_ptr;
89
ULONG   block_word;
90
ULONG   min_logical_sector;
91
ULONG   max_logical_sector;
92
ULONG   *list_word_ptr;
93
ULONG   list_word;
94
ULONG   i, j, k, l;
95
UINT    status;
96
97
98
    /* Increment the number of physical sector allocation requests.  */
99
17874
    nor_flash -> lx_nor_flash_physical_block_allocates++;
100
101
    /* Initialize the return parameters.  */
102
17874
    *physical_sector_map_entry =  (ULONG *) 0;
103
17874
    *physical_sector_address =    (ULONG *) 0;
104
105
    /* Determine if there are any free physical sectors.  */
106
17874
    if (nor_flash -> lx_nor_flash_free_physical_sectors == 0)
107
    {
108
109
        /* Increment the number of failed allocations.  */
110
        nor_flash -> lx_nor_flash_physical_block_allocate_errors++;
111
112
        /* No free physical sectors, return .  */
113
        return(LX_NO_SECTORS);
114
    }
115
116
    /* Pickup the search for a free physical sector at the specified block.  */
117
17874
    search_block =  nor_flash -> lx_nor_flash_free_block_search;
118
119
    /* Loop through the blocks to find a free physical sector.  */
120
20856
    for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++)
121
    {
122
123
        /* Setup the block word pointer to the first word of the search block.  */
124
20856
        block_word_ptr =  nor_flash -> lx_nor_flash_base_address + (search_block * nor_flash -> lx_nor_flash_words_per_block);
125
126
        /* Find the first free physical sector from the free sector bit map of this block.  */
127
23838
        for (j = 0; j < nor_flash -> lx_nor_flash_block_bit_map_words; j++)
128
        {
129
130
            /* Read this word of the free sector bit map.  */
131
#ifdef LX_DIRECT_READ
132
133
            /* Read the word directly.  */
134
            block_word =  *(block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j);
135
#else
136
20856
            status =  _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j), &block_word, 1);
137
138
            /* Check for an error from flash driver. Drivers should never return an error..  */
139
20856
            if (status)
140
            {
141
142
                /* Call system error handler.  */
143
                _lx_nor_flash_system_error(nor_flash, status);
144
145
                /* Return the error.  */
146
                return(status);
147
            }
148
#endif
149
150
            /* Are there any free sectors in this word?  */
151
20856
            if (block_word)
152
            {
153
154
                /* Yes, there are free sectors in this word.  */
155
142759
                for (k = 0; k < 32; k++)
156
                {
157
158
                    /* Is this sector free?  */
159
142759
                    if (block_word & 1)
160
                    {
161
162
                        /* Yes, this sector is free, clear the bit for this sector in the free sector map.  */
163
164
                        /* Read this word of the free sector bit map again.  */
165
#ifdef LX_DIRECT_READ
166
167
                        /* Read the word directly.  */
168
                        block_word =  *(block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j);
169
#else
170
17874
                        status =  _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j), &block_word, 1);
171
172
                        /* Check for an error from flash driver. Drivers should never return an error..  */
173
17874
                        if (status)
174
                        {
175
176
                            /* Call system error handler.  */
177
                            _lx_nor_flash_system_error(nor_flash, status);
178
179
                            /* Return the error.  */
180
                            return(status);
181
                        }
182
#endif
183
184
                        /* Clear the bit associated with the free sector to indicate it is not free.  */
185
17874
                        block_word =  block_word & ~(((ULONG) 1) << k);
186
187
                        /* Now write back free bit map word with the bit for this sector cleared.  */
188
17874
                        status =  _lx_nor_flash_driver_write(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j), &block_word, 1);
189
190
                        /* Check for an error from flash driver. Drivers should never return an error..  */
191
17874
                        if (status)
192
                        {
193
194
                            /* Call system error handler.  */
195
                            _lx_nor_flash_system_error(nor_flash, status);
196
197
                            /* Return the error.  */
198
                            return(status);
199
                        }
200
201
                        /* Determine if this is the last entry available in this block.  */
202

17874
                        if (((block_word >> 1) == 0) && (j == (nor_flash -> lx_nor_flash_block_bit_map_words - 1)))
203
                        {
204
205
                            /* This is the last physical sector in the block.  Now we need to calculate the minimum valid logical
206
                               sector and the maximum valid logical sector.  */
207
208
                            /* Setup the minimum and maximum logical sectors to the current logical sector.  */
209
1186
                            min_logical_sector =  logical_sector;
210
1186
                            max_logical_sector =  logical_sector;
211
212
                            /* Setup a pointer to the mapped list.  */
213
1186
                            list_word_ptr =  block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset;
214
215
                            /* Loop to search the mapped list.  */
216
18976
                            for (l = 0; l < nor_flash -> lx_nor_flash_physical_sectors_per_block; l++)
217
                            {
218
219
                                /* Read the mapped sector entry.  */
220
#ifdef LX_DIRECT_READ
221
222
                                /* Read the word directly.  */
223
                                list_word =  *(list_word_ptr);
224
#else
225
17790
                                status =  _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1);
226
227
                                /* Check for an error from flash driver. Drivers should never return an error..  */
228
17790
                                if (status)
229
                                {
230
231
                                    /* Call system error handler.  */
232
                                    _lx_nor_flash_system_error(nor_flash, status);
233
234
                                    /* Return the error.  */
235
                                    return(status);
236
                                }
237
#endif
238
239
                                /* Is this entry valid?  */
240
17790
                                if (list_word & LX_NOR_PHYSICAL_SECTOR_VALID)
241
                                {
242
243
                                    /* Isolate the logical sector.  */
244
17482
                                    list_word =  list_word & LX_NOR_LOGICAL_SECTOR_MASK;
245
246
                                    /* Determine if a new minimum has been found.  */
247
17482
                                    if (list_word < min_logical_sector)
248
2484
                                        min_logical_sector =  list_word;
249
250
                                    /* Determine if a new maximum has been found.  */
251
17482
                                    if (list_word != LX_NOR_LOGICAL_SECTOR_MASK)
252
                                    {
253
16296
                                        if (list_word > max_logical_sector)
254
2966
                                            max_logical_sector =  list_word;
255
                                    }
256
                                }
257
258
                                /* Move the list pointer ahead.  */
259
17790
                                list_word_ptr++;
260
                            }
261
262
                            /* Move the search pointer forward, since we know this block is exhausted.  */
263
1186
                            search_block++;
264
265
                            /* Check for wrap condition on the search block.  */
266
1186
                            if (search_block >= nor_flash -> lx_nor_flash_total_blocks)
267
                            {
268
269
                                /* Reset search block to the beginning.  */
270
146
                                search_block =  0;
271
                            }
272
273
                            /* Now write the minimum and maximum logical sector in this block.  */
274
1186
                            status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr + LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET, &min_logical_sector, 1);
275
276
                            /* Check for an error from flash driver. Drivers should never return an error..  */
277
1186
                            if (status)
278
                            {
279
280
                                /* Call system error handler.  */
281
                                _lx_nor_flash_system_error(nor_flash, status);
282
283
                                /* Return the error.  */
284
                                return(status);
285
                            }
286
287
1186
                            status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1);
288
289
                            /* Check for an error from flash driver. Drivers should never return an error..  */
290
1186
                            if (status)
291
                            {
292
293
                                /* Call system error handler.  */
294
                                _lx_nor_flash_system_error(nor_flash, status);
295
296
                                /* Return the error.  */
297
                                return(status);
298
                            }
299
                        }
300
301
                        /* Remember the block to search.  */
302
17874
                        nor_flash -> lx_nor_flash_free_block_search =  search_block;
303
304
                        /* Prepare the return information.  */
305
17874
                        *physical_sector_map_entry =  block_word_ptr + (nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + (j * 32)) + k;
306
17874
                        *physical_sector_address =    block_word_ptr + (nor_flash -> lx_nor_flash_block_physical_sector_offset) + (((j * 32) + k) * LX_NOR_SECTOR_SIZE);
307
308
                        /* Return success!  */
309
17874
                        return(LX_SUCCESS);
310
                    }
311
312
                    /* Shift down the bit map.  */
313
124885
                    block_word =  block_word >> 1;
314
315
                    /* Determine if there are any more bits set? If not, we can break out of the search of this word.  */
316
124885
                    if (block_word == 0)
317
                        break;
318
                }
319
            }
320
        }
321
322
        /* Move to the next flash block.  */
323
2982
        search_block++;
324
325
        /* Determine if we have to wrap the search block.  */
326
2982
        if (search_block >= nor_flash -> lx_nor_flash_total_blocks)
327
        {
328
329
            /* Set the search block to the beginning.  */
330
374
            search_block =  0;
331
        }
332
    }
333
334
    /* Increment the number of failed allocations.  */
335
    nor_flash -> lx_nor_flash_physical_block_allocate_errors++;
336
337
    /* Return no sector completion.  */
338
    return(LX_NO_SECTORS);
339
}
340