Skip to content

[NXP LPC176X] flash_api.c implementation #4169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 4, 2017
Merged

[NXP LPC176X] flash_api.c implementation #4169

merged 12 commits into from
May 4, 2017

Conversation

0x6d61726b
Copy link
Contributor

@0x6d61726b 0x6d61726b commented Apr 11, 2017

New features implementation

Description

For LPC176X (LPC1768/LPC1769) the flash_api.c functionality has been implemented.

The basis of this feature is the CMSIS-PACK "Keil.LPC1700_DFP.2.3.0" with the following modifications:

  1. EraseChip() function removed (not used by flash_api.h)
  2. Clock reconfiguration removed to avoid unexpected behavior. Clock value taken from function parameter

Status

READY
Tested on LPC1769 board with custom verification functions

Todos

  • perform unit test

Deploy notes

none

Steps to test or reproduce

flash_api test according to unit test template on LPC1768/LPC1769 boards.

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
  */

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
  */
Due to implementation of "flash_api.c" for NXP LPC176X the corresponding extra_labels were activated
critical.h is deprecated, replaced with "platform/mbed_critical.h"
typo corrected
mbed_critical.h replaced with "platform/mbed_critical.h" (to match template)
typo corrected
@theotherjimmy
Copy link
Contributor

@0x6d61726b Why did you post that patch? I'm honestly just curious.

typo corrected
@theotherjimmy
Copy link
Contributor

@0x6d61726b I updated the diff in your top comment to be syntax highlighted.

FYI: surrounding the diff with:
```diff
```
is how I did it.

@0x6d61726b
Copy link
Contributor Author

Thanks for updating the code comment. I will try better next time.

I did supply the patch so others can see what I have done (on an educational basis). In addition I wanted to show that the clock reconfiguration was removed on purpose. Unfortunately the blob is a black box by nature.

@theotherjimmy
Copy link
Contributor

Thanks for clarifying.

@c1728p9 Could you take a look?

@theotherjimmy
Copy link
Contributor

@0x6d61726b Could you address the Travis-CI failure?

device feature "FLASH" added
@0x6d61726b
Copy link
Contributor Author

the define DEVICE_FLASH was missing because I didn't add FLASH to "device_has" entry in target.json

@0x6d61726b
Copy link
Contributor Author

0x6d61726b commented Apr 11, 2017

Can this request be merged with #4167?
Unfortunately some modifications got added to this request (sorry, it's my first pull request)

@0xc0170
Copy link
Contributor

0xc0170 commented Apr 12, 2017

Can this request be merged with #4167?

Will go in first.

Can you share the test results from flash HAL and FlashIAP ? both, for what toolchains they were tested?

Interesting to see edited the flashblob :-)

@0x6d61726b
Copy link
Contributor Author

0x6d61726b commented Apr 14, 2017

The tests were performed on a LPC1769 LPCXpresso board. Compiliation was done with VisualGDB compiler (TOOLCHAIN_GCC_ARM).

The Debug output from the SRAM Flash Kernel test is here: log.txt. The used flash functions are:

FlashIAP flash;
result = flash.init();
flashStart = flash.get_flash_start();
flashSize = flash.get_flash_size();
page_size = flash.get_page_size();
result = flash.erase(flashStart, flashSize);
result = flash.read(page_buffer, pageAddr, page_size);
result = flash.program(page_buffer, pageAddr, page_size);

@c1728p9
Copy link
Contributor

c1728p9 commented Apr 14, 2017

Hi @0x6d61726b can you create a PR to the FlashAlgo repo with the modifications you made? If this flash algo needs to be updated in the future this will make it easier.

@0x6d61726b
Copy link
Contributor Author

0x6d61726b commented Apr 14, 2017

Hi @c1728p9, I am not sure if I am qualified doing so, because I may break something when applying the same changes to the FalshAlgo code. For mbed flash_api.c blob I removed the clock setup (which is unnecessary) and also the ChipErase on purpose. For whatever the FlashAlgo repository is additionally used, that code may be needed there.

It would be a good idea to document that repository on the handbook in the Flash IAP section.

@sg-
Copy link
Contributor

sg- commented Apr 19, 2017

Is the stack used by IAP ROM calls allocated and protected in the LPC target code memory map?

@theotherjimmy
Copy link
Contributor

bump @0x6d61726b

@0x6d61726b
Copy link
Contributor Author

If I understood the user manual correct, the already allocated user stack is used, but the top 32 bits of the local SRAM shall not be used, because it is used by the flash programming commands.

32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack usage in the user allocated stack space is 128 bytes and it grows downwards.

Shall I add the modification to the existing linker scripts to avoid the address space of 0x10007FE0 to 0x10007FFF to avoid stack corruption?

@0xc0170
Copy link
Contributor

0xc0170 commented Apr 26, 2017

Shall I add the modification to the existing linker scripts to avoid the address space of 0x10007FE0 to 0x10007FFF to avoid stack corruption?

I would say yes. @c1728p9 What do you think?

@c1728p9
Copy link
Contributor

c1728p9 commented Apr 26, 2017

Yeah, the space there definitely needs to be reserved.

NXP LPC176x/5x User Manual UM10360 Rev 4.1:
32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack 
usage in the user allocated stack space is 128 bytes and it grows downwards.
NXP LPC176x/5x User Manual UM10360 Rev 4.1:
32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack 
usage in the user allocated stack space is 128 bytes and it grows downwards.
NXP LPC176x/5x User Manual UM10360 Rev 4.1:
32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack 
usage in the user allocated stack space is 128 bytes and it grows downwards.
NXP LPC176x/5x User Manual UM10360 Rev 4.1:
32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack 
usage in the user allocated stack space is 128 bytes and it grows downwards.
NXP LPC176x/5x User Manual UM10360 Rev 4.1:
32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack 
usage in the user allocated stack space is 128 bytes and it grows downwards.
NXP LPC176x/5x User Manual UM10360 Rev 4.1:
32.3.2.8 RAM used by IAP command handler
Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack 
usage in the user allocated stack space is 128 bytes and it grows downwards.
@0x6d61726b
Copy link
Contributor Author

space is reserved. IAR file already spared the topmost 32 bytes.

@0xc0170
Copy link
Contributor

0xc0170 commented May 2, 2017

@c1728p9 Happy with this patch? With the modifications done to FlashAlgo?

@0xc0170
Copy link
Contributor

0xc0170 commented May 2, 2017

/morph test

@mbed-bot
Copy link

mbed-bot commented May 2, 2017

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test

Output

mbed Build Number: 126

All builds and test passed!

@adbridge
Copy link
Contributor

adbridge commented May 5, 2017

This is reliant on #4167 which is targeted for 5.5.0, thus re-targeting this one also for 5.5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants