Martin Kojtal
6a6561028e
LPC1768: flash erase/write require a critical section
...
From RM:
32.3.2.6 Interrupts during IAP
The on-chip flash memory is not accessible during erase/write operations. When the user
application code starts executing the interrupt vectors from the user flash area are active.
The user should either disable interrupts, or ensure that user interrupt vectors are active in
RAM and that the interrupt handlers reside in RAM, before making a flash erase/write IAP
call. The IAP code does not use or disable interrupts.
2017-09-25 19:18:06 +02:00
0x6d61726b
29c7b34dfa
LPC176X flash_api.h implementation
...
For LPC176X (LPC1768/LPC1769) the flash driver has been implemented according to the CMSIS-PACK Keil.LPC1700_DFP.2.3.0 driver with the following changes in FlashPrg.c:
1. EraseChip() function removed (not used by flash_api)
2. Clock reconfiguration removed and clock value taken from function parameter to avoid unexpected behavior.
Full patch of FlashPrg.c:
--- Keil.LPC1700_DFP.2.3.0\Flash\LPC_IAP\FlashPrg_orig.c 2016-12-08 13:10:10.000000000 +0200
+++ Keil.LPC1700_DFP.2.3.0\Flash\LPC_IAP\FlashPrg.c 2017-04-11 20:02:37.000000000 +0200
@@ -191,90 +191,15 @@
* fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
* Return Value: 0 - OK, 1 - Failed
*/
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
-#if defined LPC1XXX || defined LPC11U6X
- CCLK = 12000; // 12MHz Internal RC Oscillator
+ CCLK = clk / 1000; // CCLK value is in kHz, clk in Hz
- MAINCLKSEL = 0; // Select Internal RC Oscillator
- MAINCLKUEN = 1; // Update Main Clock Source
- MAINCLKUEN = 0; // Toggle Update Register
- MAINCLKUEN = 1;
-// while (!(MAINCLKUEN & 1)); // Wait until updated
- MAINCLKDIV = 1; // Set Main Clock divider to 1
-
- MEMMAP = 0x02; // User Flash Mode
-#endif
-
-#ifdef LPC17XX
- IAP.stat = 0; // Note: Some Bootloader versions don't set the status if this command is executed
- IAP.cmd = 54; // Read Part ID
- IAP_Call (&IAP.cmd, &IAP.stat); // Call IAP Command
- if (IAP.stat) return (1); // Command Failed
-
- switch ((IAP.res[0] >> 24) & 0xFF) {
- case 0x25:
- // Part ID LPC1759 = 0x25113737
- // Part ID LPC1758 = 0x25013F37
- // Part ID LPC1756 = 0x25011723
- // Part ID LPC1754 = 0x25011722
- // Part ID LPC1752 = 0x25001121
- // Part ID LPC1751 = 0x25001118 / 0x25001110
- case 0x26:
- // Part ID LPC1769 = 0x26113F37
- // Part ID LPC1768 = 0x26013F37
- // Part ID LPC1767 = 0x26012837
- // Part ID LPC1766 = 0x26013F33
- // Part ID LPC1765 = 0x26013733
- // Part ID LPC1764 = 0x26011922
- CCLK = 4000; // 4MHz Internal RC Oscillator
- break;
- case 0x27:
- // Part ID LPC1778 = 0x27193F47
- // Part ID LPC1777 = 0x27193747
- // Part ID LPC1776 = 0x27191F43
- // Part ID LPC1774 = 0x27011132
- // Part ID LPC1772 = 0x27011121
- case 0x20: // found out during test
- case 0x28:
- // Part ID LPC1788 = 0x281D3F47
- // Part ID LPC1787 = 0x281D3747
- // Part ID LPC1786 = 0x281D1F43
- // Part ID LPC1785 = 0x281D1743
- case 0x48: // Part ID LPC4088 = 0x481D3F47
- case 0x47: // Part ID LPC4078 = 0x47193F47
- // Part ID LPC4076 = 0x47191F43
- // Part ID LPC4074 = 0x47011132
- CCLK = 12000; // 12MHz Internal RC Oscillator
- break;
- default:
- CCLK = 4000; // 4MHz Internal RC Oscillator
- }
-
- CLKSRCSEL = 0x00; // sysclk = IRC
-
- PLL0CON = 0x00; // Disable PLL (use Oscillator)
- PLL0FEED = 0xAA; // Feed Sequence Part #1
- PLL0FEED = 0x55; // Feed Sequence Part #2
-
- switch ((IAP.res[0] >> 24) & 0xFF) {
- case 0x27: // LPC177x
- case 0x20: // LPC178x
- case 0x28: // LPC178x
- case 0x48: // LPC407x
- case 0x47: // LPC408x
- CCLKSEL = 0x01; // use Sysclk devided by 1 for CPU
- break;
- default:
- CCLKSEL = 0x00; // CPU clk divider is 1
- }
-
MEMMAP = 0x01; // User Flash Mode
-#endif
return (0);
}
/*
@@ -283,37 +208,12 @@
* Return Value: 0 - OK, 1 - Failed
*/
int UnInit (unsigned long fnc) {
return (0);
}
-
-
-/*
- * Erase complete Flash Memory
- * Return Value: 0 - OK, 1 - Failed
- */
-
-int EraseChip (void) {
-
- IAP.cmd = 50; // Prepare Sector for Erase
- IAP.par[0] = 0; // Start Sector
- IAP.par[1] = END_SECTOR; // End Sector
- IAP_Call (&IAP.cmd, &IAP.stat); // Call IAP Command
- if (IAP.stat) return (1); // Command Failed
-
- IAP.cmd = 52; // Erase Sector
- IAP.par[0] = 0; // Start Sector
- IAP.par[1] = END_SECTOR; // End Sector
- IAP.par[2] = CCLK; // CCLK in kHz
- IAP_Call (&IAP.cmd, &IAP.stat); // Call IAP Command
- if (IAP.stat) return (1); // Command Failed
-
- return (0); // Finished without Errors
-}
-
/*
* Erase Sector in Flash Memory
* Parameter: adr: Sector Address
* Return Value: 0 - OK, 1 - Failed
*/
2017-04-11 21:03:45 +02:00