GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nor_flash_physical_sector_allocate.c Lines: 50 67 74.6 %
Date: 2026-03-06 18:45:40 Branches: 33 44 75.0 %

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

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