GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nor_flash_sector_release.c Lines: 17 25 68.0 %
Date: 2024-03-11 05:20:25 Branches: 5 10 50.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_sector_release                        PORTABLE C      */
42
/*                                                           6.3.0        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    William E. Lamie, Microsoft Corporation                             */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function releases a logical sector from being managed in the   */
50
/*    NOR flash.                                                          */
51
/*                                                                        */
52
/*  INPUT                                                                 */
53
/*                                                                        */
54
/*    nor_flash                             NOR flash instance            */
55
/*    logical_sector                        Logical sector number         */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    return status                                                       */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _lx_nor_flash_driver_write            Driver flash sector write     */
64
/*    _lx_nor_flash_driver_read             Driver flash sector read      */
65
/*    _lx_nor_flash_block_reclaim           Reclaim one flash block       */
66
/*    _lx_nor_flash_sector_mapping_cache_invalidate                       */
67
/*                                          Invalidate cache entry        */
68
/*    _lx_nor_flash_logical_sector_find     Find logical sector           */
69
/*    _lx_nor_flash_system_error            Internal system error handler */
70
/*    tx_mutex_get                          Get thread protection         */
71
/*    tx_mutex_put                          Release thread protection     */
72
/*                                                                        */
73
/*  CALLED BY                                                             */
74
/*                                                                        */
75
/*    Application Code                                                    */
76
/*                                                                        */
77
/*  RELEASE HISTORY                                                       */
78
/*                                                                        */
79
/*    DATE              NAME                      DESCRIPTION             */
80
/*                                                                        */
81
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
82
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
83
/*                                            resulting in version 6.1    */
84
/*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
85
/*                                            resulting in version 6.1.7  */
86
/*  10-31-2023     Xiuwen Cai               Modified comment(s),          */
87
/*                                            added mapping bitmap cache, */
88
/*                                            added obsolete count cache, */
89
/*                                            resulting in version 6.3.0  */
90
/*                                                                        */
91
/**************************************************************************/
92
104
UINT  _lx_nor_flash_sector_release(LX_NOR_FLASH *nor_flash, ULONG logical_sector)
93
{
94
95
UINT    status;
96
ULONG   *mapping_address;
97
ULONG   mapping_entry;
98
ULONG   *sector_address;
99
ULONG   i;
100
#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
101
ULONG   block;
102
#endif
103
104
105
#ifdef LX_THREAD_SAFE_ENABLE
106
107
    /* Obtain the thread safe mutex.  */
108
    tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
109
#endif
110
111
    /* Increment the number of read requests.  */
112
104
    nor_flash -> lx_nor_flash_read_requests++;
113
114
    /* See if we can find the sector in the current mapping.  */
115
104
    _lx_nor_flash_logical_sector_find(nor_flash, logical_sector, LX_FALSE, &mapping_address, &sector_address);
116
117
    /* Determine if the logical sector was found.  */
118
104
    if (mapping_address)
119
    {
120
121
        /* Yes, we were able to find the logical sector.  */
122
123
        /* Read in the old sector mapping.  */
124
#ifdef LX_DIRECT_READ
125
126
        /* Read the word directly.  */
127
        mapping_entry =  *(mapping_address);
128
#else
129
102
        status =  _lx_nor_flash_driver_read(nor_flash, mapping_address, &mapping_entry, 1);
130
131
        /* Check for an error from flash driver. Drivers should never return an error..  */
132
102
        if (status)
133
        {
134
135
            /* Call system error handler.  */
136
            _lx_nor_flash_system_error(nor_flash, status);
137
138
#ifdef LX_THREAD_SAFE_ENABLE
139
140
            /* Release the thread safe mutex.  */
141
            tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
142
#endif
143
144
            /* Return status.  */
145
            return(LX_ERROR);
146
        }
147
#endif
148
149
        /* Mark this sector as invalid.  */
150
        /* Now clear bits 31 and 30, which indicates this sector is now obsoleted.  */
151
102
        mapping_entry =  mapping_entry & ~(((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID) | ((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED));
152
153
        /* Write the value back to the flash to clear bits 31 & 30.  */
154
102
        status =  _lx_nor_flash_driver_write(nor_flash, mapping_address, &mapping_entry, 1);
155
156
        /* Check for an error from flash driver. Drivers should never return an error..  */
157
102
        if (status)
158
        {
159
160
            /* Call system error handler.  */
161
            _lx_nor_flash_system_error(nor_flash, status);
162
163
#ifdef LX_THREAD_SAFE_ENABLE
164
165
            /* Release the thread safe mutex.  */
166
            tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
167
#endif
168
169
            /* Return status.  */
170
            return(LX_ERROR);
171
        }
172
173
#ifndef LX_NOR_DISABLE_EXTENDED_CACHE
174
#ifdef LX_NOR_ENABLE_MAPPING_BITMAP
175
176
        /* Determine if the logical sector is within the mapping bitmap.  */
177
        if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector)
178
        {
179
180
            /* Set the bit in the mapping bitmap.  */
181
            nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] &= (ULONG)~(1 << (logical_sector & 31));
182
        }
183
#endif
184
#endif
185
186
        /* Increment the number of obsolete physical sectors.  */
187
102
        nor_flash -> lx_nor_flash_obsolete_physical_sectors++;
188
189
#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
190
191
        /* Get the block number from mapping address.  */
192
        block = (ULONG)(mapping_address - nor_flash -> lx_nor_flash_base_address) / nor_flash -> lx_nor_flash_words_per_block;
193
194
        /* Determine if this block is within the range of the obsolete count cache.  */
195
        if (block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
196
        {
197
198
            /* Increment the obsolete count for this block.  */
199
            nor_flash -> lx_nor_flash_extended_cache_obsolete_count[block] ++;
200
        }
201
#endif
202
203
        /* Decrement the number of mapped physical sectors.  */
204
102
        nor_flash -> lx_nor_flash_mapped_physical_sectors--;
205
206
        /* Ensure the sector mapping cache no longer has this sector.  */
207
102
        _lx_nor_flash_sector_mapping_cache_invalidate(nor_flash, logical_sector);
208
209
        /* Determine if there are less than two block's worth of free sectors.  */
210
102
        i =  0;
211
102
        while (nor_flash -> lx_nor_flash_free_physical_sectors <= nor_flash -> lx_nor_flash_physical_sectors_per_block)
212
        {
213
214
            /* Attempt to reclaim one physical block.  */
215
            _lx_nor_flash_block_reclaim(nor_flash);
216
217
            /* Increment the block count.  */
218
            i++;
219
220
            /* Have we exceeded the number of blocks in the system?  */
221
            if (i >= nor_flash -> lx_nor_flash_total_blocks)
222
            {
223
224
                /* Yes, break out of the loop.  */
225
                break;
226
            }
227
        }
228
229
        /* Set the status to success.  */
230
102
        status =  LX_SUCCESS;
231
    }
232
    else
233
    {
234
235
        /* Could not find the logical sector.  */
236
2
        status =  LX_SECTOR_NOT_FOUND;
237
    }
238
239
#ifdef LX_THREAD_SAFE_ENABLE
240
241
    /* Release the thread safe mutex.  */
242
    tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
243
#endif
244
245
    /* Return status.  */
246
104
    return(status);
247
}
248