1 //*****************************************************************************
\r
3 // flash.c - Driver for programming the on-chip flash.
\r
5 // Copyright (c) 2005,2006 Luminary Micro, Inc. All rights reserved.
\r
7 // Software License Agreement
\r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
\r
10 // exclusively on LMI's Stellaris Family of microcontroller products.
\r
12 // The software is owned by LMI and/or its suppliers, and is protected under
\r
13 // applicable copyright laws. All rights are reserved. Any use in violation
\r
14 // of the foregoing restrictions may subject the user to criminal sanctions
\r
15 // under applicable laws, as well as to civil liability for the breach of the
\r
16 // terms and conditions of this license.
\r
18 // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r
24 // This is part of revision 991 of the Stellaris Driver Library.
\r
26 //*****************************************************************************
\r
28 //*****************************************************************************
\r
30 //! \addtogroup flash_api
\r
33 //*****************************************************************************
\r
35 #include "../hw_flash.h"
\r
36 #include "../hw_ints.h"
\r
37 #include "../hw_memmap.h"
\r
38 #include "../hw_sysctl.h"
\r
39 #include "../hw_types.h"
\r
42 #include "interrupt.h"
\r
44 //*****************************************************************************
\r
46 //! Gets the number of processor clocks per micro-second.
\r
48 //! This function returns the number of clocks per micro-second, as presently
\r
49 //! known by the flash controller.
\r
51 //! \return Returns the number of processor clocks per micro-second.
\r
53 //*****************************************************************************
\r
54 #if defined(GROUP_usecget) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
59 // Return the number of clocks per micro-second.
\r
61 return(HWREG(FLASH_USECRL) + 1);
\r
65 //*****************************************************************************
\r
67 //! Sets the number of processor clocks per micro-second.
\r
69 //! \param ulClocks is the number of processor clocks per micro-second.
\r
71 //! This function is used to tell the flash controller the number of processor
\r
72 //! clocks per micro-second. This value must be programmed correctly or the
\r
73 //! flash most likely will not program correctly; it has no affect on reading
\r
78 //*****************************************************************************
\r
79 #if defined(GROUP_usecset) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
81 FlashUsecSet(unsigned long ulClocks)
\r
84 // Set the number of clocks per micro-second.
\r
86 HWREG(FLASH_USECRL) = ulClocks - 1;
\r
90 //*****************************************************************************
\r
92 //! Erases a block of flash.
\r
94 //! \param ulAddress is the start address of the flash block to be erased.
\r
96 //! This function will erase a 1 kB block of the on-chip flash. After erasing,
\r
97 //! the block will be filled with 0xFF bytes. Read-only and execute-only
\r
98 //! blocks cannot be erased.
\r
100 //! This function will not return until the block has been erased.
\r
102 //! \return Returns 0 on success, or -1 if an invalid block address was
\r
103 //! specified or the block is write-protected.
\r
105 //*****************************************************************************
\r
106 #if defined(GROUP_erase) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
108 FlashErase(unsigned long ulAddress)
\r
111 // Check the arguments.
\r
113 ASSERT(!(ulAddress & (FLASH_ERASE_SIZE - 1)));
\r
116 // Clear the flash access interrupt.
\r
118 HWREG(FLASH_FCMISC) = FLASH_FCMISC_ACCESS;
\r
121 // Erase the block.
\r
123 HWREG(FLASH_FMA) = ulAddress;
\r
124 HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
\r
127 // Wait until the word has been programmed.
\r
129 while(HWREG(FLASH_FMC) & FLASH_FMC_ERASE)
\r
134 // Return an error if an access violation occurred.
\r
136 if(HWREG(FLASH_FCRIS) & FLASH_FCRIS_ACCESS)
\r
148 //*****************************************************************************
\r
150 //! Programs flash.
\r
152 //! \param pulData is a pointer to the data to be programmed.
\r
153 //! \param ulAddress is the starting address in flash to be programmed. Must
\r
154 //! be a multiple of four.
\r
155 //! \param ulCount is the number of bytes to be programmed. Must be a multiple
\r
158 //! This function will program a sequence of words into the on-chip flash.
\r
159 //! Programming each location consists of the result of an AND operation
\r
160 //! of the new data and the existing data; in other words bits that contain
\r
161 //! 1 can remain 1 or be changed to 0, but bits that are 0 cannot be changed
\r
162 //! to 1. Therefore, a word can be programmed multiple times as long as these
\r
163 //! rules are followed; if a program operation attempts to change a 0 bit to
\r
164 //! a 1 bit, that bit will not have its value changed.
\r
166 //! Since the flash is programmed one word at a time, the starting address and
\r
167 //! byte count must both be multiples of four. It is up to the caller to
\r
168 //! verify the programmed contents, if such verification is required.
\r
170 //! This function will not return until the data has been programmed.
\r
172 //! \return Returns 0 on success, or -1 if a programming error is encountered.
\r
174 //*****************************************************************************
\r
175 #if defined(GROUP_program) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
177 FlashProgram(unsigned long *pulData, unsigned long ulAddress,
\r
178 unsigned long ulCount)
\r
181 // Check the arguments.
\r
183 ASSERT(!(ulAddress & 3));
\r
184 ASSERT(!(ulCount & 3));
\r
187 // Clear the flash access interrupt.
\r
189 HWREG(FLASH_FCMISC) = FLASH_FCMISC_ACCESS;
\r
192 // Loop over the words to be programmed.
\r
197 // Program the next word.
\r
199 HWREG(FLASH_FMA) = ulAddress;
\r
200 HWREG(FLASH_FMD) = *pulData;
\r
201 HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
\r
204 // Wait until the word has been programmed.
\r
206 while(HWREG(FLASH_FMC) & FLASH_FMC_WRITE)
\r
211 // Increment to the next word.
\r
219 // Return an error if an access violation occurred.
\r
221 if(HWREG(FLASH_FCRIS) & FLASH_FCRIS_ACCESS)
\r
233 //*****************************************************************************
\r
235 //! Gets the protection setting for a block of flash.
\r
237 //! \param ulAddress is the start address of the flash block to be queried.
\r
239 //! This function will get the current protection for the specified 2 kB block
\r
240 //! of flash. Each block can be read/write, read-only, or execute-only.
\r
241 //! Read/write blocks can be read, executed, erased, and programmed. Read-only
\r
242 //! blocks can be read and executed. Execute-only blocks can only be executed;
\r
243 //! processor and debugger data reads are not allowed.
\r
245 //! \return Returns the protection setting for this block. See
\r
246 //! FlashProtectSet() for possible values.
\r
248 //*****************************************************************************
\r
249 #if defined(GROUP_protectget) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
251 FlashProtectGet(unsigned long ulAddress)
\r
253 unsigned long ulFMPRE, ulFMPPE;
\r
256 // Check the argument.
\r
258 ASSERT(!(ulAddress & (FLASH_PROTECT_SIZE - 1)));
\r
261 // Read the flash protection register and get the bits that apply to the
\r
262 // specified block.
\r
264 ulFMPRE = HWREG(FLASH_FMPRE);
\r
265 ulFMPPE = HWREG(FLASH_FMPPE);
\r
266 switch((((ulFMPRE >> (ulAddress / FLASH_PROTECT_SIZE)) &
\r
267 FLASH_FMP_BLOCK_0) << 1) |
\r
268 ((ulFMPPE >> (ulAddress / FLASH_PROTECT_SIZE)) & FLASH_FMP_BLOCK_0))
\r
271 // This block is marked as execute only (i.e. it can not be erased or
\r
272 // programmed, and the only reads allowed are via the instruction fecth
\r
278 return(FlashExecuteOnly);
\r
282 // This block is marked as read only (i.e. it can not be erased or
\r
287 return(FlashReadOnly);
\r
291 // This block is read/write; it can be read, erased, and programmed.
\r
296 return(FlashReadWrite);
\r
302 //*****************************************************************************
\r
304 //! Sets the protection setting for a block of flash.
\r
306 //! \param ulAddress is the start address of the flash block to be protected.
\r
307 //! \param eProtect is the protection to be applied to the block. Can be one
\r
308 //! of \b FlashReadWrite, \b FlashReadOnly, or \b FlashExecuteOnly.
\r
310 //! This function will set the protection for the specified 2 kB block of
\r
311 //! flash. Blocks which are read/write can be made read-only or execute-only.
\r
312 //! Blocks which are read-only can be made execute-only. Blocks which are
\r
313 //! execute-only cannot have their protection modified. Attempts to make the
\r
314 //! block protection less stringent (i.e. read-only to read/write) will result
\r
315 //! in a failure (and be prevented by the hardware).
\r
317 //! Changes to the flash protection are maintained only until the next reset.
\r
318 //! This allows the application to be executed in the desired flash protection
\r
319 //! environment to check for inappropriate flash access (via the flash
\r
320 //! interrupt). To make the flash protection permanent, use the
\r
321 //! FlashProtectSave() function.
\r
323 //! \return Returns 0 on success, or -1 if an invalid address or an invalid
\r
324 //! protection was specified.
\r
326 //*****************************************************************************
\r
327 #if defined(GROUP_protectset) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
329 FlashProtectSet(unsigned long ulAddress, tFlashProtection eProtect)
\r
331 unsigned long ulProtectRE, ulProtectPE;
\r
334 // Check the argument.
\r
336 ASSERT(!(ulAddress & (FLASH_PROTECT_SIZE - 1)));
\r
337 ASSERT((eProtect == FlashReadWrite) || (eProtect == FlashReadOnly) ||
\r
338 (eProtect == FlashExecuteOnly));
\r
341 // Convert the address into a block number.
\r
343 ulAddress /= FLASH_PROTECT_SIZE;
\r
346 // Get the current protection.
\r
348 ulProtectRE = HWREG(FLASH_FMPRE);
\r
349 ulProtectPE = HWREG(FLASH_FMPPE);
\r
352 // Set the protection based on the requested proection.
\r
357 // Make this block execute only.
\r
359 case FlashExecuteOnly:
\r
362 // Turn off the read and program bits for this block.
\r
364 ulProtectRE &= ~(FLASH_FMP_BLOCK_0 << ulAddress);
\r
365 ulProtectPE &= ~(FLASH_FMP_BLOCK_0 << ulAddress);
\r
368 // We're done handling this protection.
\r
374 // Make this block read only.
\r
376 case FlashReadOnly:
\r
379 // The block can not be made read only if it is execute only.
\r
381 if(((ulProtectRE >> ulAddress) & FLASH_FMP_BLOCK_0) !=
\r
388 // Make this block read only.
\r
390 ulProtectPE &= ~(FLASH_FMP_BLOCK_0 << ulAddress);
\r
393 // We're done handling this protection.
\r
399 // Make this block read/write.
\r
401 case FlashReadWrite:
\r
405 // The block can not be made read/write if it is not already
\r
408 if((((ulProtectRE >> ulAddress) & FLASH_FMP_BLOCK_0) !=
\r
409 FLASH_FMP_BLOCK_0) ||
\r
410 (((ulProtectPE >> ulAddress) & FLASH_FMP_BLOCK_0) !=
\r
411 FLASH_FMP_BLOCK_0))
\r
417 // The block is already read/write, so there is nothing to do.
\r
424 // Set the new protection.
\r
426 HWREG(FLASH_FMPRE) = ulProtectRE;
\r
427 HWREG(FLASH_FMPPE) = ulProtectPE;
\r
436 //*****************************************************************************
\r
438 //! Saves the flash protection settings.
\r
440 //! This function will make the currently programmed flash protection settings
\r
441 //! permanent. This is a non-reversible operation; a chip reset or power cycle
\r
442 //! will not change the flash protection.
\r
444 //! This function will not return until the protection has been saved.
\r
446 //! \return Returns 0 on success, or -1 if a hardware error is encountered.
\r
448 //*****************************************************************************
\r
449 #if defined(GROUP_protectsave) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
451 FlashProtectSave(void)
\r
454 // Tell the flash controller to write the flash read protection register.
\r
456 HWREG(FLASH_FMA) = 0;
\r
457 HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_COMT;
\r
460 // Wait until the write has completed.
\r
462 while(HWREG(FLASH_FMC) & FLASH_FMC_COMT)
\r
467 // Tell the flash controller to write the flash program protection
\r
470 HWREG(FLASH_FMA) = 1;
\r
471 HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_COMT;
\r
474 // Wait until the write has completed.
\r
476 while(HWREG(FLASH_FMC) & FLASH_FMC_COMT)
\r
487 //*****************************************************************************
\r
489 //! Registers an interrupt handler for the flash interrupt.
\r
491 //! \param pfnHandler is a pointer to the function to be called when the flash
\r
492 //! interrupt occurs.
\r
494 //! This sets the handler to be called when the flash interrupt occurs. The
\r
495 //! flash controller can generate an interrupt when an invalid flash access
\r
496 //! occurs, such as trying to program or erase a read-only block, or trying to
\r
497 //! read from an execute-only block. It can also generate an interrupt when a
\r
498 //! program or erase operation has completed. The interrupt will be
\r
499 //! automatically enabled when the handler is registered.
\r
501 //! \sa IntRegister() for important information about registering interrupt
\r
506 //*****************************************************************************
\r
507 #if defined(GROUP_intregister) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
509 FlashIntRegister(void (*pfnHandler)(void))
\r
512 // Register the interrupt handler, returning an error if an error occurs.
\r
514 IntRegister(INT_FLASH, pfnHandler);
\r
517 // Enable the flash interrupt.
\r
519 IntEnable(INT_FLASH);
\r
523 //*****************************************************************************
\r
525 //! Unregisters the interrupt handler for the flash interrupt.
\r
527 //! This function will clear the handler to be called when the flash interrupt
\r
528 //! occurs. This will also mask off the interrupt in the interrupt controller
\r
529 //! so that the interrupt handler is no longer called.
\r
531 //! \sa IntRegister() for important information about registering interrupt
\r
536 //*****************************************************************************
\r
537 #if defined(GROUP_intunregister) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
539 FlashIntUnregister(void)
\r
542 // Disable the interrupt.
\r
544 IntDisable(INT_FLASH);
\r
547 // Unregister the interrupt handler.
\r
549 IntUnregister(INT_FLASH);
\r
553 //*****************************************************************************
\r
555 //! Enables individual flash controller interrupt sources.
\r
557 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
\r
558 //! Can be any of the \b FLASH_FCIM_PROGRAM or \b FLASH_FCIM_ACCESS values.
\r
560 //! Enables the indicated flash controller interrupt sources. Only the sources
\r
561 //! that are enabled can be reflected to the processor interrupt; disabled
\r
562 //! sources have no effect on the processor.
\r
566 //*****************************************************************************
\r
567 #if defined(GROUP_intenable) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
569 FlashIntEnable(unsigned long ulIntFlags)
\r
572 // Enable the specified interrupts.
\r
574 HWREG(FLASH_FCIM) |= ulIntFlags;
\r
578 //*****************************************************************************
\r
580 //! Disables individual flash controller interrupt sources.
\r
582 //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
\r
583 //! Can be any of the \b FLASH_FCIM_PROGRAM or \b FLASH_FCIM_ACCESS values.
\r
585 //! Disables the indicated flash controller interrupt sources. Only the
\r
586 //! sources that are enabled can be reflected to the processor interrupt;
\r
587 //! disabled sources have no effect on the processor.
\r
591 //*****************************************************************************
\r
592 #if defined(GROUP_intdisable) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
594 FlashIntDisable(unsigned long ulIntFlags)
\r
597 // Disable the specified interrupts.
\r
599 HWREG(FLASH_FCIM) &= ~(ulIntFlags);
\r
603 //*****************************************************************************
\r
605 //! Gets the current interrupt status.
\r
607 //! \param bMasked is false if the raw interrupt status is required and true if
\r
608 //! the masked interrupt status is required.
\r
610 //! This returns the interrupt status for the flash controller. Either the raw
\r
611 //! interrupt status or the status of interrupts that are allowed to reflect to
\r
612 //! the processor can be returned.
\r
614 //! \return The current interrupt status, enumerated as a bit field of
\r
615 //! \b FLASH_FCMISC_PROGRAM and \b FLASH_FCMISC_ACCESS.
\r
617 //*****************************************************************************
\r
618 #if defined(GROUP_intgetstatus) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
620 FlashIntGetStatus(tBoolean bMasked)
\r
623 // Return either the interrupt status or the raw interrupt status as
\r
628 return(HWREG(FLASH_FCMISC));
\r
632 return(HWREG(FLASH_FCRIS));
\r
637 //*****************************************************************************
\r
639 //! Clears flash controller interrupt sources.
\r
641 //! \param ulIntFlags is the bit mask of the interrupt sources to be cleared.
\r
642 //! Can be any of the \b FLASH_FCMISC_PROGRAM or \b FLASH_FCMISC_ACCESS
\r
645 //! The specified flash controller interrupt sources are cleared, so that they
\r
646 //! no longer assert. This must be done in the interrupt handler to keep it
\r
647 //! from being called again immediately upon exit.
\r
651 //*****************************************************************************
\r
652 #if defined(GROUP_intclear) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
654 FlashIntClear(unsigned long ulIntFlags)
\r
657 // Clear the flash interrupt.
\r
659 HWREG(FLASH_FCMISC) = ulIntFlags;
\r
663 //*****************************************************************************
\r
665 // Close the Doxygen group.
\r
668 //*****************************************************************************
\r