1 //*****************************************************************************
2 //
3 //! @file am_hal_stimer.h
4 //!
5 //! @brief Functions for interfacing with the system timer (STIMER).
6 //!
7 //! @addtogroup stimer3 STIMER - System Timer
8 //! @ingroup apollo3_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, 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_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 #ifndef AM_HAL_STIMER_H
48 #define AM_HAL_STIMER_H
49 
50 #ifdef __cplusplus
51 extern "C"
52 {
53 #endif
54 
55 //
56 //! Compute address of a given COMPARE register.
57 //! @note - The parameter n should be 0 (as only 1 stimer module exists).
58 //!         For Apollo3, the parameter r should be 0-7 (compare) or 0-3 (capture).
59 //
60 #define AM_REG_STIMER_COMPARE(n, r)     (CTIMERADDRn(CTIMER, n, SCMPR0) +   \
61                                          (r * (offsetof(CTIMER_Type, SCMPR1) - offsetof(CTIMER_Type, SCMPR0))))
62 
63 //! Compute address of a given CAPTURE register. r should be 0-3.
64 #define AM_REG_STIMER_CAPTURE(n, r)     (CTIMERADDRn(CTIMER, n, SCAPT0) +   \
65                                          (r * (offsetof(CTIMER_Type, SCAPT1) - offsetof(CTIMER_Type, SCAPT0))))
66 
67 //! Compute address of a given NVRAM register. r should be 0-3.
68 #define AM_REG_STIMER_NVRAM(n, r)       (CTIMERADDRn(CTIMER, n, SNVR0) +    \
69                                          (r * (offsetof(CTIMER_Type, SNVR1) - offsetof(CTIMER_Type, SNVR0))))
70 
71 
72 //*****************************************************************************
73 //
74 //! @name Interrupt Status Bits
75 //! @brief Interrupt Status Bits for enable/disble use
76 //!
77 //! These macros may be used to set and clear interrupt bits
78 //! @{
79 //
80 //*****************************************************************************
81 #define AM_HAL_STIMER_INT_COMPAREA         CTIMER_STMINTSTAT_COMPAREA_Msk
82 #define AM_HAL_STIMER_INT_COMPAREB         CTIMER_STMINTSTAT_COMPAREB_Msk
83 #define AM_HAL_STIMER_INT_COMPAREC         CTIMER_STMINTSTAT_COMPAREC_Msk
84 #define AM_HAL_STIMER_INT_COMPARED         CTIMER_STMINTSTAT_COMPARED_Msk
85 #define AM_HAL_STIMER_INT_COMPAREE         CTIMER_STMINTSTAT_COMPAREE_Msk
86 #define AM_HAL_STIMER_INT_COMPAREF         CTIMER_STMINTSTAT_COMPAREF_Msk
87 #define AM_HAL_STIMER_INT_COMPAREG         CTIMER_STMINTSTAT_COMPAREG_Msk
88 #define AM_HAL_STIMER_INT_COMPAREH         CTIMER_STMINTSTAT_COMPAREH_Msk
89 
90 #define AM_HAL_STIMER_INT_OVERFLOW         CTIMER_STMINTSTAT_OVERFLOW_Msk
91 
92 #define AM_HAL_STIMER_INT_CAPTUREA         CTIMER_STMINTSTAT_CAPTUREA_Msk
93 #define AM_HAL_STIMER_INT_CAPTUREB         CTIMER_STMINTSTAT_CAPTUREB_Msk
94 #define AM_HAL_STIMER_INT_CAPTUREC         CTIMER_STMINTSTAT_CAPTUREC_Msk
95 #define AM_HAL_STIMER_INT_CAPTURED         CTIMER_STMINTSTAT_CAPTURED_Msk
96 
97 //! @}
98 
99 //*****************************************************************************
100 //
101 //! @name STimer Configuration Bits
102 //! @brief Interrupt Status Bits for enable/disble use
103 //!
104 //! These macros may be used to set and clear interrupt bits
105 //! @{
106 //
107 //*****************************************************************************
108 #define AM_HAL_STIMER_CFG_THAW              _VAL2FLD(CTIMER_STCFG_FREEZE,       CTIMER_STCFG_FREEZE_THAW)
109 #define AM_HAL_STIMER_CFG_FREEZE            _VAL2FLD(CTIMER_STCFG_FREEZE,       CTIMER_STCFG_FREEZE_FREEZE)
110 #define AM_HAL_STIMER_CFG_RUN               _VAL2FLD(CTIMER_STCFG_CLEAR,        CTIMER_STCFG_CLEAR_RUN)
111 #define AM_HAL_STIMER_CFG_CLEAR             _VAL2FLD(CTIMER_STCFG_CLEAR,        CTIMER_STCFG_CLEAR_CLEAR)
112 #define AM_HAL_STIMER_CFG_COMPARE_A_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_A_EN, CTIMER_STCFG_COMPARE_A_EN_ENABLE)
113 #define AM_HAL_STIMER_CFG_COMPARE_B_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_B_EN, CTIMER_STCFG_COMPARE_B_EN_ENABLE)
114 #define AM_HAL_STIMER_CFG_COMPARE_C_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_C_EN, CTIMER_STCFG_COMPARE_C_EN_ENABLE)
115 #define AM_HAL_STIMER_CFG_COMPARE_D_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_D_EN, CTIMER_STCFG_COMPARE_D_EN_ENABLE)
116 #define AM_HAL_STIMER_CFG_COMPARE_E_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_E_EN, CTIMER_STCFG_COMPARE_E_EN_ENABLE)
117 #define AM_HAL_STIMER_CFG_COMPARE_F_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_F_EN, CTIMER_STCFG_COMPARE_F_EN_ENABLE)
118 #define AM_HAL_STIMER_CFG_COMPARE_G_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_G_EN, CTIMER_STCFG_COMPARE_G_EN_ENABLE)
119 #define AM_HAL_STIMER_CFG_COMPARE_H_ENABLE  _VAL2FLD(CTIMER_STCFG_COMPARE_H_EN, CTIMER_STCFG_COMPARE_H_EN_ENABLE)
120 
121 //! @}
122 
123 //*****************************************************************************
124 //
125 //! @name Clock Configuration options
126 //! @brief STimer Configuration register options.
127 //!
128 //! These options are to be used with the am_hal_stimer_config() function.
129 //!  @{
130 //
131 //*****************************************************************************
132 #define AM_HAL_STIMER_NO_CLK            _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_NOCLK)
133 #define AM_HAL_STIMER_HFRC_3MHZ         _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_HFRC_DIV16)
134 #define AM_HAL_STIMER_HFRC_187_5KHZ     _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_HFRC_DIV256)
135 #define AM_HAL_STIMER_XTAL_32KHZ        _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_XTAL_DIV1)
136 #define AM_HAL_STIMER_XTAL_16KHZ        _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_XTAL_DIV2)
137 #define AM_HAL_STIMER_XTAL_1KHZ         _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_XTAL_DIV32)
138 #define AM_HAL_STIMER_LFRC_1KHZ         _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_LFRC_DIV1)
139 #define AM_HAL_STIMER_HFRC_CTIMER0A     _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_CTIMER0A)
140 #define AM_HAL_STIMER_HFRC_CTIMER0B     _VAL2FLD(CTIMER_STCFG_CLKSEL, CTIMER_STCFG_CLKSEL_CTIMER0B)
141 //! @}
142 
143 
144 
145 //*****************************************************************************
146 //
147 //! @name Capture Control Register options.
148 //! @brief Configuration options for capture control register.
149 //!
150 //! These options are to be used with the am_hal_stimer_capture_control_set
151 //! function.
152 //!  @{
153 //
154 //*****************************************************************************
155 #define AM_HAL_STIMER_CAPTURE0_ENABLE   _VAL2FLD(CTIMER_CAPTURECONTROL_CAPTURE0, CTIMER_CAPTURECONTROL_CAPTURE0_ENABLE)
156 #define AM_HAL_STIMER_CAPTURE1_ENABLE   _VAL2FLD(CTIMER_CAPTURECONTROL_CAPTURE1, CTIMER_CAPTURECONTROL_CAPTURE1_ENABLE)
157 #define AM_HAL_STIMER_CAPTURE2_ENABLE   _VAL2FLD(CTIMER_CAPTURECONTROL_CAPTURE2, CTIMER_CAPTURECONTROL_CAPTURE2_ENABLE)
158 #define AM_HAL_STIMER_CAPTURE3_ENABLE   _VAL2FLD(CTIMER_CAPTURECONTROL_CAPTURE3, CTIMER_CAPTURECONTROL_CAPTURE3_ENABLE)
159 
160 //! @}
161 
162 //*****************************************************************************
163 //
164 //! Stimer configuration structure
165 //
166 //*****************************************************************************
167 typedef struct
168 {
169     //
170     //! Configuration options for the STIMER
171     //
172     uint32_t ui32STimerConfig;
173 }
174 am_hal_stimer_config_t;
175 
176 //*****************************************************************************
177 //
178 // External function definitions
179 //
180 //*****************************************************************************
181 
182 //*****************************************************************************
183 //
184 //! @brief Set up the stimer.
185 //!
186 //! @param ui32STimerConfig - The value to load into the configuration reg.
187 //!
188 //! @note This function should be used to perform the initial set-up of the
189 //! stimer.
190 //!
191 //! @return The 32-bit current config of the STimer Config register
192 //
193 //*****************************************************************************
194 extern uint32_t am_hal_stimer_config(uint32_t ui32STimerConfig);
195 
196 //*****************************************************************************
197 //
198 //! @brief Get the current stimer value.
199 //!
200 //! This function can be used to read, uninvasively, the value in the stimer.
201 //!
202 //! @return The 32-bit value from the STimer counter register.
203 //
204 //*****************************************************************************
205 extern uint32_t am_hal_stimer_counter_get(void);
206 
207 //*****************************************************************************
208 //
209 //! @brief Clear the stimer counter.
210 //!
211 //! This function clears the STimer Counter and leaves the stimer running.
212 //
213 //*****************************************************************************
214 extern void     am_hal_stimer_counter_clear(void);
215 
216 //*****************************************************************************
217 //
218 //! @brief Set the compare value.
219 //!
220 //! @param ui32CmprInstance - The compare register instance number (0-7).
221 //! @param ui32Delta - The value to add to the STimer counter and load into
222 //!        the comparator register.
223 //!
224 //! @note There is no way to set an absolute value into a comparator register.
225 //!       Only deltas added to the STimer counter can be written to the compare
226 //!       registers.
227 //
228 //*****************************************************************************
229 extern void     am_hal_stimer_compare_delta_set(uint32_t ui32CmprInstance,
230                                                 uint32_t ui32Delta);
231 //*****************************************************************************
232 //
233 //! @brief Get the current stimer compare register value.
234 //!
235 //! @param ui32CmprInstance is the compare register instance number (0-7).
236 //!
237 //! This function can be used to read the value in an stimer compare register.
238 //
239 //*****************************************************************************
240 extern uint32_t am_hal_stimer_compare_get(uint32_t ui32CmprInstance);
241 
242 //*****************************************************************************
243 //
244 //! @brief Start capturing data with the specified capture register.
245 //!
246 //! @param ui32CaptureNum - The Capture Register Number to read (0-3).
247 //! @param ui32GPIONumber - The pin number.
248 //! @param bPolarity: false (0) = Capture on low to high transition.
249 //!                   true  (1) = Capture on high to low transition.
250 //!
251 //! Use this function to start capturing.
252 //
253 //*****************************************************************************
254 extern void     am_hal_stimer_capture_start(uint32_t ui32CaptureNum,
255                                             uint32_t ui32GPIONumber,
256                                             bool bPolarity);
257 
258 //*****************************************************************************
259 //
260 //! @brief Start capturing data with the specified capture register.
261 //!
262 //! @param ui32CaptureNum - - The Capture Register Number to read.
263 //!
264 //! Use this function to start capturing.
265 //
266 //*****************************************************************************
267 extern void     am_hal_stimer_capture_stop(uint32_t ui32CaptureNum);
268 
269 //*****************************************************************************
270 //
271 //! @brief Get the current stimer capture register value.
272 //!
273 //! @param ui32CaptureNum - The Capture Register Number to read.
274 //!
275 //! This function can be used to read the value in an stimer capture register.
276 //!
277 //! @return Stimer Capture Register Value.
278 //
279 //*****************************************************************************
280 extern uint32_t am_hal_stimer_capture_get(uint32_t ui32CaptureNum);
281 
282 //*****************************************************************************
283 //
284 //! @brief Get the current stimer nvram register value.
285 //!
286 //! @param ui32NvramNum - The NVRAM Register Number.
287 //! @param ui32NvramVal - The value to write to NVRAM.
288 //!
289 //! This function can be used to read the value in an stimer NVRAM register.
290 //
291 //*****************************************************************************
292 extern void am_hal_stimer_nvram_set(uint32_t ui32NvramNum, uint32_t ui32NvramVal);
293 
294 //*****************************************************************************
295 //
296 //! @brief Get the current stimer nvram register value.
297 //!
298 //! @param ui32NvramNum - The NVRAM Register Number to read.
299 //!
300 //! This function can be used to read the value in an stimer NVRAM register.
301 //!
302 //! @return NVRAM Register Value
303 //!
304 //
305 //*****************************************************************************
306 extern uint32_t am_hal_stimer_nvram_get(uint32_t ui32NvramNum);
307 
308 //*****************************************************************************
309 //
310 //! @brief Enables the selected system timer interrupt.
311 //!
312 //! This function will enable the selected interrupts in the STIMER interrupt
313 //! enable register.
314 
315 //! @note In order to receive an interrupt from an stimer component,
316 //! you will need to enable the interrupt for that component in this main
317 //! register, as well as in the stimer configuration register (accessible though
318 //! am_hal_stimer_config()), and in the NVIC.
319 //!
320 //! @param ui32Interrupt - The interrupt to be used.
321 //! @parblock
322 //!
323 //! ui32Interrupt should be the logical OR of one or more of the following
324 //! values:
325 //!
326 //!     AM_HAL_STIMER_INT_COMPAREA
327 //!     AM_HAL_STIMER_INT_COMPAREB
328 //!     AM_HAL_STIMER_INT_COMPAREC
329 //!     AM_HAL_STIMER_INT_COMPARED
330 //!     AM_HAL_STIMER_INT_COMPAREE
331 //!     AM_HAL_STIMER_INT_COMPAREF
332 //!     AM_HAL_STIMER_INT_COMPAREG
333 //!     AM_HAL_STIMER_INT_COMPAREH
334 //!
335 //!     AM_HAL_STIMER_INT_OVERFLOW
336 //!
337 //!     AM_HAL_STIMER_INT_CAPTUREA
338 //!     AM_HAL_STIMER_INT_CAPTUREB
339 //!     AM_HAL_STIMER_INT_CAPTUREC
340 //!     AM_HAL_STIMER_INT_CAPTURED
341 //! @endparblock
342 //
343 //*****************************************************************************
344 extern void     am_hal_stimer_int_enable(uint32_t ui32Interrupt);
345 
346 //*****************************************************************************
347 //
348 //! @brief Return the enabled stimer interrupts.
349 //!
350 //! This function will return all enabled interrupts in the STIMER
351 //! interrupt enable register.
352 //!
353 //! @return return enabled interrupts. This will be a logical or of:
354 //!
355 //!     AM_HAL_STIMER_INT_COMPAREA
356 //!     AM_HAL_STIMER_INT_COMPAREB
357 //!     AM_HAL_STIMER_INT_COMPAREC
358 //!     AM_HAL_STIMER_INT_COMPARED
359 //!     AM_HAL_STIMER_INT_COMPAREE
360 //!     AM_HAL_STIMER_INT_COMPAREF
361 //!     AM_HAL_STIMER_INT_COMPAREG
362 //!     AM_HAL_STIMER_INT_COMPAREH
363 //!     AM_HAL_STIMER_INT_OVERFLOW
364 //!     AM_HAL_STIMER_INT_CAPTUREA
365 //!     AM_HAL_STIMER_INT_CAPTUREB
366 //!     AM_HAL_STIMER_INT_CAPTUREC
367 //!     AM_HAL_STIMER_INT_CAPTURED
368 //
369 //*****************************************************************************
370 extern uint32_t am_hal_stimer_int_enable_get(void);
371 
372 //*****************************************************************************
373 //
374 //! @brief Disables the selected stimer interrupt.
375 //!
376 //! This function will disable the selected interrupts in the STIMER
377 //! interrupt register.
378 //!
379 //! @param ui32Interrupt - The interrupt to be used.
380 //! @parblock
381 //!
382 //! ui32Interrupt should be the logical OR of one or more of the following
383 //! values:
384 //!
385 //!     AM_HAL_STIMER_INT_COMPAREA
386 //!     AM_HAL_STIMER_INT_COMPAREB
387 //!     AM_HAL_STIMER_INT_COMPAREC
388 //!     AM_HAL_STIMER_INT_COMPARED
389 //!     AM_HAL_STIMER_INT_COMPAREE
390 //!     AM_HAL_STIMER_INT_COMPAREF
391 //!     AM_HAL_STIMER_INT_COMPAREG
392 //!     AM_HAL_STIMER_INT_COMPAREH
393 //!
394 //!     AM_HAL_STIMER_INT_OVERFLOW
395 //!
396 //!     AM_HAL_STIMER_INT_CAPTUREA
397 //!     AM_HAL_STIMER_INT_CAPTUREB
398 //!     AM_HAL_STIMER_INT_CAPTUREC
399 //!     AM_HAL_STIMER_INT_CAPTURED
400 //! @endparblock
401 //
402 //*****************************************************************************
403 extern void     am_hal_stimer_int_disable(uint32_t ui32Interrupt);
404 
405 //*****************************************************************************
406 //
407 //! @brief Sets the selected stimer interrupt.
408 //!
409 //! This function will set the selected interrupts in the STIMER
410 //! interrupt register.
411 //!
412 //! @param ui32Interrupt - The interrupt to be used.
413 //! @parblock
414 //!
415 //! ui32Interrupt should be the logical OR of one or more of the following
416 //! values:
417 //!
418 //!     AM_HAL_STIMER_INT_COMPAREA
419 //!     AM_HAL_STIMER_INT_COMPAREB
420 //!     AM_HAL_STIMER_INT_COMPAREC
421 //!     AM_HAL_STIMER_INT_COMPARED
422 //!     AM_HAL_STIMER_INT_COMPAREE
423 //!     AM_HAL_STIMER_INT_COMPAREF
424 //!     AM_HAL_STIMER_INT_COMPAREG
425 //!     AM_HAL_STIMER_INT_COMPAREH
426 //!
427 //!     AM_HAL_STIMER_INT_OVERFLOW
428 //!
429 //!     AM_HAL_STIMER_INT_CAPTUREA
430 //!     AM_HAL_STIMER_INT_CAPTUREB
431 //!     AM_HAL_STIMER_INT_CAPTUREC
432 //!     AM_HAL_STIMER_INT_CAPTURED
433 //! @endparblock
434 //
435 //*****************************************************************************
436 extern void     am_hal_stimer_int_set(uint32_t ui32Interrupt);
437 
438 //*****************************************************************************
439 //
440 //! @brief Clears the selected stimer interrupt.
441 //!
442 //! This function will clear the selected interrupts in the STIMER
443 //! interrupt register.
444 //!
445 //! @param ui32Interrupt - The interrupt to be used.
446 //! @parblock
447 //!
448 //! ui32Interrupt should be the logical OR of one or more of the following
449 //! values:
450 //!
451 //!     AM_HAL_STIMER_INT_COMPAREA
452 //!     AM_HAL_STIMER_INT_COMPAREB
453 //!     AM_HAL_STIMER_INT_COMPAREC
454 //!     AM_HAL_STIMER_INT_COMPARED
455 //!     AM_HAL_STIMER_INT_COMPAREE
456 //!     AM_HAL_STIMER_INT_COMPAREF
457 //!     AM_HAL_STIMER_INT_COMPAREG
458 //!     AM_HAL_STIMER_INT_COMPAREH
459 //!
460 //!     AM_HAL_STIMER_INT_OVERFLOW
461 //!
462 //!     AM_HAL_STIMER_INT_CAPTUREA
463 //!     AM_HAL_STIMER_INT_CAPTUREB
464 //!     AM_HAL_STIMER_INT_CAPTUREC
465 //!     AM_HAL_STIMER_INT_CAPTURED
466 //! @endparblock
467 //
468 //*****************************************************************************
469 extern void     am_hal_stimer_int_clear(uint32_t ui32Interrupt);
470 
471 //*****************************************************************************
472 //
473 //! @brief Returns either the enabled or raw stimer interrupt status.
474 //!
475 //! This function will return the stimer interrupt status.
476 //!
477 //! @param bEnabledOnly if true returns the status of the enabled interrupts
478 //! only.
479 //!
480 //! The return value will be the logical OR of one or more of the following
481 //! values:
482 //!
483 //! @return Returns the stimer interrupt status.
484 //
485 //*****************************************************************************
486 extern uint32_t am_hal_stimer_int_status_get(bool bEnabledOnly);
487 
488 
489 #ifdef __cplusplus
490 }
491 #endif
492 
493 #endif // AM_HAL_STIMER_H
494 
495 //*****************************************************************************
496 //
497 // End Doxygen group.
498 //! @}
499 //
500 //*****************************************************************************
501