<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/12501">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add flash ASF4 driver<br><br>this is imported from the Atmel Start website<br><br>Change-Id: I5eccb37da64c7def7b99418773d09b6d98664432<br>---<br>A config/hpl_nvmctrl_config.h<br>M gcc/Makefile<br>A hal/documentation/flash.rst<br>A hal/include/hal_flash.h<br>A hal/include/hpl_flash.h<br>A hal/include/hpl_user_area.h<br>A hal/src/hal_flash.c<br>A hpl/nvmctrl/hpl_nvmctrl.c<br>8 files changed, 1,705 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/config/hpl_nvmctrl_config.h b/config/hpl_nvmctrl_config.h</span><br><span>new file mode 100644</span><br><span>index 0000000..daaba85</span><br><span>--- /dev/null</span><br><span>+++ b/config/hpl_nvmctrl_config.h</span><br><span>@@ -0,0 +1,36 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Auto-generated config file hpl_nvmctrl_config.h */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef HPL_NVMCTRL_CONFIG_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define HPL_NVMCTRL_CONFIG_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// <<< Use Configuration Wizard in Context Menu >>></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// <h> Basic Settings</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// <o> Power Reduction Mode During Sleep</span><br><span style="color: hsl(120, 100%, 40%);">+// <0x00=> Wake On Access</span><br><span style="color: hsl(120, 100%, 40%);">+// <0x01=> Wake Up Instant</span><br><span style="color: hsl(120, 100%, 40%);">+// <0x03=> Disabled</span><br><span style="color: hsl(120, 100%, 40%);">+// <id> nvm_arch_sleepprm</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef CONF_NVM_SLEEPPRM</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONF_NVM_SLEEPPRM 0</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// <q> AHB0 Cache Disable</span><br><span style="color: hsl(120, 100%, 40%);">+// <i> Indicate whether AHB0 cache is disable or not</span><br><span style="color: hsl(120, 100%, 40%);">+// <id> nvm_arch_cache0</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef CONF_NVM_CACHE0</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONF_NVM_CACHE0 0</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// <q> AHB1 Cache Disable</span><br><span style="color: hsl(120, 100%, 40%);">+// <i> Indicate whether AHB1 cache is disable or not</span><br><span style="color: hsl(120, 100%, 40%);">+// <id> nvm_arch_cache1</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef CONF_NVM_CACHE1</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONF_NVM_CACHE1 0</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// </h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// <<< end of configuration section >>></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif // HPL_NVMCTRL_CONFIG_H</span><br><span>diff --git a/gcc/Makefile b/gcc/Makefile</span><br><span>index 231ed39..f7c5b65 100644</span><br><span>--- a/gcc/Makefile</span><br><span>+++ b/gcc/Makefile</span><br><span>@@ -41,6 +41,7 @@</span><br><span> usb/device \</span><br><span> hpl/oscctrl \</span><br><span> gcc/gcc \</span><br><span style="color: hsl(120, 100%, 40%);">+hpl/nvmctrl \</span><br><span> hpl/usb \</span><br><span> hpl/core \</span><br><span> hpl/cmcc</span><br><span>@@ -52,6 +53,7 @@</span><br><span> usb/class/dfu/device/dfudf.o \</span><br><span> hal/utils/src/utils_syscalls.o \</span><br><span> hpl/dmac/hpl_dmac.o \</span><br><span style="color: hsl(120, 100%, 40%);">+hpl/nvmctrl/hpl_nvmctrl.o \</span><br><span> gcc/system_same54.o \</span><br><span> hpl/usb/hpl_usb.o \</span><br><span> hal/src/hal_delay.o \</span><br><span>@@ -65,6 +67,7 @@</span><br><span> hpl/mclk/hpl_mclk.o \</span><br><span> hpl/ramecc/hpl_ramecc.o \</span><br><span> usb/usb_protocol.o \</span><br><span style="color: hsl(120, 100%, 40%);">+hal/src/hal_flash.o \</span><br><span> hal/src/hal_init.o \</span><br><span> gcc/gcc/startup_same54.o \</span><br><span> hal/src/hal_usb_device.o \</span><br><span>@@ -81,12 +84,14 @@</span><br><span> usb/device/usbdc.o \</span><br><span> hal/src/hal_atomic.o</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> OBJS_AS_ARGS +=  \</span><br><span> "hal/src/hal_io.o" \</span><br><span> "hpl/core/hpl_core_m4.o" \</span><br><span> "usb/class/dfu/device/dfudf.o" \</span><br><span> "hal/utils/src/utils_syscalls.o" \</span><br><span> "hpl/dmac/hpl_dmac.o" \</span><br><span style="color: hsl(120, 100%, 40%);">+"hpl/nvmctrl/hpl_nvmctrl.o" \</span><br><span> "gcc/system_same54.o" \</span><br><span> "hpl/usb/hpl_usb.o" \</span><br><span> "hal/src/hal_delay.o" \</span><br><span>@@ -100,6 +105,7 @@</span><br><span> "hpl/mclk/hpl_mclk.o" \</span><br><span> "hpl/ramecc/hpl_ramecc.o" \</span><br><span> "usb/usb_protocol.o" \</span><br><span style="color: hsl(120, 100%, 40%);">+"hal/src/hal_flash.o" \</span><br><span> "hal/src/hal_init.o" \</span><br><span> "gcc/gcc/startup_same54.o" \</span><br><span> "hal/src/hal_usb_device.o" \</span><br><span>@@ -125,6 +131,7 @@</span><br><span> "hpl/ramecc/hpl_ramecc.d" \</span><br><span> "hpl/core/hpl_core_m4.d" \</span><br><span> "hal/utils/src/utils_syscalls.d" \</span><br><span style="color: hsl(120, 100%, 40%);">+"hpl/nvmctrl/hpl_nvmctrl.d" \</span><br><span> "usb/class/dfu/device/dfudf.d" \</span><br><span> "gcc/gcc/startup_same54.d" \</span><br><span> "hpl/usb/hpl_usb.d" \</span><br><span>@@ -136,6 +143,7 @@</span><br><span> "hpl/core/hpl_init.d" \</span><br><span> "hpl/pm/hpl_pm.d" \</span><br><span> "usb/usb_protocol.d" \</span><br><span style="color: hsl(120, 100%, 40%);">+"hal/src/hal_flash.d" \</span><br><span> "hpl/gclk/hpl_gclk.d" \</span><br><span> "hal/src/hal_usb_device.d" \</span><br><span> "hpl/dmac/hpl_dmac.d" \</span><br><span>@@ -199,7 +207,7 @@</span><br><span>         @echo ARM/GNU C Compiler</span><br><span>     $(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \</span><br><span> -D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \</span><br><span style="color: hsl(0, 100%, 40%);">--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \</span><br><span style="color: hsl(120, 100%, 40%);">+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \</span><br><span> -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"</span><br><span>   @echo Finished building: $<</span><br><span> </span><br><span>@@ -208,7 +216,7 @@</span><br><span>     @echo ARM/GNU Assembler</span><br><span>      $(QUOTE)arm-none-eabi-as$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \</span><br><span> -D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \</span><br><span style="color: hsl(0, 100%, 40%);">--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \</span><br><span style="color: hsl(120, 100%, 40%);">+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \</span><br><span> -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"</span><br><span>    @echo Finished building: $<</span><br><span> </span><br><span>@@ -217,7 +225,7 @@</span><br><span>     @echo ARM/GNU Preprocessing Assembler</span><br><span>        $(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \</span><br><span> -D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \</span><br><span style="color: hsl(0, 100%, 40%);">--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \</span><br><span style="color: hsl(120, 100%, 40%);">+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \</span><br><span> -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"</span><br><span>   @echo Finished building: $<</span><br><span> </span><br><span>diff --git a/hal/documentation/flash.rst b/hal/documentation/flash.rst</span><br><span>new file mode 100644</span><br><span>index 0000000..fcc86e6</span><br><span>--- /dev/null</span><br><span>+++ b/hal/documentation/flash.rst</span><br><span>@@ -0,0 +1,52 @@</span><br><span style="color: hsl(120, 100%, 40%);">+The Flash Driver</span><br><span style="color: hsl(120, 100%, 40%);">+================</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Flash is a re-programmable memory that retains program and data</span><br><span style="color: hsl(120, 100%, 40%);">+storage even with power off.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+User can write or read several bytes from any valid address in a flash.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+As to the erase/lock/unlock command, the input parameter of address should</span><br><span style="color: hsl(120, 100%, 40%);">+be a bytes address aligned with the page start, otherwise, the command will fail</span><br><span style="color: hsl(120, 100%, 40%);">+to be executed. At the meantime, the number of pages that can be locked or unlocked</span><br><span style="color: hsl(120, 100%, 40%);">+at once depends on region size of the flash. User can get the real number</span><br><span style="color: hsl(120, 100%, 40%);">+from the function return value which could be different for the different devices.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Features</span><br><span style="color: hsl(120, 100%, 40%);">+--------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+* Initialization/de-initialization</span><br><span style="color: hsl(120, 100%, 40%);">+* Writing/Reading bytes</span><br><span style="color: hsl(120, 100%, 40%);">+* Locking/Unlocking/Erasing pages</span><br><span style="color: hsl(120, 100%, 40%);">+* Notifications about errors or being ready for a new command</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Applications</span><br><span style="color: hsl(120, 100%, 40%);">+------------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+* Mini disk which can retain program and data storage</span><br><span style="color: hsl(120, 100%, 40%);">+* Boot loader</span><br><span style="color: hsl(120, 100%, 40%);">+* Non volatile storage</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Dependencies</span><br><span style="color: hsl(120, 100%, 40%);">+------------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The peripheral which controls a re-programmable flash memory.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Concurrency</span><br><span style="color: hsl(120, 100%, 40%);">+-----------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+N/A</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Limitations</span><br><span style="color: hsl(120, 100%, 40%);">+-----------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+User should pay attention to set a proper stack size in their application,</span><br><span style="color: hsl(120, 100%, 40%);">+since the driver manages a temporary buffer in stack to cache unchanged data</span><br><span style="color: hsl(120, 100%, 40%);">+when calling flash write and erase function.</span><br><span style="color: hsl(120, 100%, 40%);">+Due to flash memory architecture of SAMD21/D20/L21/L22/C20/C21/D09/D10/D11/R21,</span><br><span style="color: hsl(120, 100%, 40%);">+write operation erazes row content before each write.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Known issues and workarounds</span><br><span style="color: hsl(120, 100%, 40%);">+----------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+N/A</span><br><span>diff --git a/hal/include/hal_flash.h b/hal/include/hal_flash.h</span><br><span>new file mode 100644</span><br><span>index 0000000..8216afd</span><br><span>--- /dev/null</span><br><span>+++ b/hal/include/hal_flash.h</span><br><span>@@ -0,0 +1,209 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Flash related functionality declaration.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_start</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \page License</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Subject to your compliance with these terms, you may use Microchip</span><br><span style="color: hsl(120, 100%, 40%);">+ * software and any derivatives exclusively with Microchip products.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is your responsibility to comply with third party license terms applicable</span><br><span style="color: hsl(120, 100%, 40%);">+ * to your use of third party software (including open source software) that</span><br><span style="color: hsl(120, 100%, 40%);">+ * may accompany Microchip software.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,</span><br><span style="color: hsl(120, 100%, 40%);">+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL</span><br><span style="color: hsl(120, 100%, 40%);">+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT</span><br><span style="color: hsl(120, 100%, 40%);">+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY</span><br><span style="color: hsl(120, 100%, 40%);">+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_stop</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _HAL_FLASH_H_INCLUDED</span><br><span style="color: hsl(120, 100%, 40%);">+#define _HAL_FLASH_H_INCLUDED</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <hpl_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \addtogroup doc_driver_hal_flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Forward declaration of flash_descriptor. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct flash_descriptor;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** The callback types */</span><br><span style="color: hsl(120, 100%, 40%);">+enum flash_cb_type {</span><br><span style="color: hsl(120, 100%, 40%);">+      /** Callback type for ready to accept a new command */</span><br><span style="color: hsl(120, 100%, 40%);">+        FLASH_CB_READY,</span><br><span style="color: hsl(120, 100%, 40%);">+       /** Callback type for error */</span><br><span style="color: hsl(120, 100%, 40%);">+        FLASH_CB_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+       FLASH_CB_N</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Prototype of callback on FLASH</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef void (*flash_cb_t)(struct flash_descriptor *const descr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief FLASH HAL callbacks</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct flash_callbacks {</span><br><span style="color: hsl(120, 100%, 40%);">+  /** Callback invoked when ready to accept a new command */</span><br><span style="color: hsl(120, 100%, 40%);">+    flash_cb_t cb_ready;</span><br><span style="color: hsl(120, 100%, 40%);">+  /** Callback invoked when error occurs */</span><br><span style="color: hsl(120, 100%, 40%);">+     flash_cb_t cb_error;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief FLASH HAL driver struct for asynchronous access</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct flash_descriptor {</span><br><span style="color: hsl(120, 100%, 40%);">+        /** Pointer to FLASH device instance */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct _flash_device dev;</span><br><span style="color: hsl(120, 100%, 40%);">+     /** Callbacks for asynchronous transfer */</span><br><span style="color: hsl(120, 100%, 40%);">+    struct flash_callbacks callbacks;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Initialize the FLASH HAL instance and hardware for callback mode</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Initialize FLASH HAL with interrupt mode (uses callbacks).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] hw Pointer to the hardware base.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Initialize status.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_init(struct flash_descriptor *flash, void *const hw);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Deinitialize the FLASH HAL instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Abort transfer, disable and reset FLASH, and deinitialize software.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Deinitialze status.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_deinit(struct flash_descriptor *flash);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Writes a number of bytes to a page in the internal Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr  Destination bytes address to write into flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  buffer    Pointer to a buffer where the content</span><br><span style="color: hsl(120, 100%, 40%);">+ *                        will be written to the flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  length    Number of bytes to write</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Write status.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_write(struct flash_descriptor *flash, uint32_t dst_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Appends a number of bytes to a page in the internal Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This functions never erases the flash before writing.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr  Destination bytes address to write to flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  buffer    Pointer to a buffer with data to write to flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  length    Number of bytes to append</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Append status.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_append(struct flash_descriptor *flash, uint32_t dst_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Reads a number of bytes to a page in the internal Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  src_addr  Source bytes address to read from flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] buffer    Pointer to a buffer where the content</span><br><span style="color: hsl(120, 100%, 40%);">+ *                        of the read pages will be stored</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  length    Number of bytes to read</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Read status.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_read(struct flash_descriptor *flash, uint32_t src_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Register a function as FLASH transfer completion callback</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] type Callback type (\ref flash_cb_type).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] func Pointer to callback function.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \retval -1 Error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_register_callback(struct flash_descriptor *flash, const enum flash_cb_type type, flash_cb_t func);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Execute lock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr  Destination bytes address aligned with page</span><br><span style="color: hsl(120, 100%, 40%);">+ *                        start to be locked</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  page_nums Number of pages to be locked</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Real locked numbers of pages.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_lock(struct flash_descriptor *flash, const uint32_t dst_addr, const uint32_t page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Execute unlock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr  Destination bytes address aligned with page</span><br><span style="color: hsl(120, 100%, 40%);">+ *                        start to be unlocked</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  page_nums Number of pages to be unlocked</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Real unlocked numbers of pages.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_unlock(struct flash_descriptor *flash, const uint32_t dst_addr, const uint32_t page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Execute erase in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr  Destination bytes address aligned with page</span><br><span style="color: hsl(120, 100%, 40%);">+ *                        start to be erased</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  page_nums Number of pages to be erased</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \retval -1 Error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_erase(struct flash_descriptor *flash, const uint32_t dst_addr, const uint32_t page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the flash page size</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in, out] flash Pointer to the HAL FLASH instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The flash page size</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t flash_get_page_size(struct flash_descriptor *flash);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the number of flash page</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in, out] flash Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The flash total page numbers</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t flash_get_total_pages(struct flash_descriptor *flash);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Retrieve the current driver version</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Current driver version.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t flash_get_version(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+/**@}*/</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* ifndef _HAL_FLASH_H_INCLUDED */</span><br><span>diff --git a/hal/include/hpl_flash.h b/hal/include/hpl_flash.h</span><br><span>new file mode 100644</span><br><span>index 0000000..3a42c44</span><br><span>--- /dev/null</span><br><span>+++ b/hal/include/hpl_flash.h</span><br><span>@@ -0,0 +1,265 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief FLASH related functionality declaration.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_start</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \page License</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Subject to your compliance with these terms, you may use Microchip</span><br><span style="color: hsl(120, 100%, 40%);">+ * software and any derivatives exclusively with Microchip products.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is your responsibility to comply with third party license terms applicable</span><br><span style="color: hsl(120, 100%, 40%);">+ * to your use of third party software (including open source software) that</span><br><span style="color: hsl(120, 100%, 40%);">+ * may accompany Microchip software.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,</span><br><span style="color: hsl(120, 100%, 40%);">+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL</span><br><span style="color: hsl(120, 100%, 40%);">+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT</span><br><span style="color: hsl(120, 100%, 40%);">+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY</span><br><span style="color: hsl(120, 100%, 40%);">+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_stop</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _HPL_FLASH_H_INCLUDED</span><br><span style="color: hsl(120, 100%, 40%);">+#define _HPL_FLASH_H_INCLUDED</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \addtogroup hpl__flash__group FLASH HPL APIs</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**@{*/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <compiler.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "hpl_irq.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief FLASH device structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The FLASH device structure forward declaration.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct _flash_device;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** The callback types */</span><br><span style="color: hsl(120, 100%, 40%);">+enum _flash_cb_type { FLASH_DEVICE_CB_READY, FLASH_DEVICE_CB_ERROR, FLASH_DEVICE_CB_N };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief FLASH interrupt handlers structure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct _flash_callback {</span><br><span style="color: hsl(120, 100%, 40%);">+     /** Ready to accept new command handler */</span><br><span style="color: hsl(120, 100%, 40%);">+    void (*ready_cb)(struct _flash_device *device);</span><br><span style="color: hsl(120, 100%, 40%);">+       /** Error handler */</span><br><span style="color: hsl(120, 100%, 40%);">+  void (*error_cb)(struct _flash_device *device);</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief FLASH descriptor device structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct _flash_device {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct _flash_callback flash_cb; /*!< Interrupt handers  */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct _irq_descriptor irq;      /*!< Interrupt descriptor */</span><br><span style="color: hsl(120, 100%, 40%);">+      void *                 hw;       /*!< Hardware module instance handler */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Initialize FLASH.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function does low level FLASH configuration.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] hw The pointer to hardware instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Initialize status.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _flash_init(struct _flash_device *const device, void *const hw);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Deinitialize FLASH.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_deinit(struct _flash_device *const device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Reads a number of bytes in the internal Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  src_addr      Source bytes address to read from flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buffer        Pointer to a buffer where the content</span><br><span style="color: hsl(120, 100%, 40%);">+ *                           of the read page will be stored</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  length        Number of bytes to read</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_read(struct _flash_device *const device, const uint32_t src_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Writes a number of bytes in the internal Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  dst_addr      Destination bytes address to write into flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  buffer        Pointer to buffer where the data to</span><br><span style="color: hsl(120, 100%, 40%);">+ *                           write is stored</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  length        Number of bytes to write</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_write(struct _flash_device *const device, const uint32_t dst_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Appends a number of bytes in the internal Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  dst_addr      Destination bytes address to write into flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  buffer        Pointer to buffer with data to write to flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  length        Number of bytes to write</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_append(struct _flash_device *const device, const uint32_t dst_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Execute lock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr      Destination bytes address aligned with page</span><br><span style="color: hsl(120, 100%, 40%);">+ *                            start to be locked</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  page_nums     Number of pages to be locked</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Real locked numbers of pages.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _flash_lock(struct _flash_device *const device, const uint32_t dst_addr, uint32_t page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Execute unlock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr      Destination bytes address aligned with page</span><br><span style="color: hsl(120, 100%, 40%);">+ *                            start to be unlocked</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  page_nums     Number of pages to be unlocked</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Real unlocked numbers of pages.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _flash_unlock(struct _flash_device *const device, const uint32_t dst_addr, uint32_t page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief check whether the region which is pointed by address</span><br><span style="color: hsl(120, 100%, 40%);">+ *         is locked</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr      Destination bytes address to check</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return The lock status of assigned address.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+bool _flash_is_locked(struct _flash_device *const device, const uint32_t dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \brief Execute erase in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  dst_addr      Destination bytes address aligned with page</span><br><span style="color: hsl(120, 100%, 40%);">+ *                            start to be erased</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in]  page_nums     Number of pages to be erased</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_erase(struct _flash_device *const device, const uint32_t dst_addr, uint32_t page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the flash page size.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The flash page size</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _flash_get_page_size(struct _flash_device *const device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the numbers of flash page.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The flash total page numbers</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _flash_get_total_pages(struct _flash_device *const device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the number of wait states for read and write operations.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The number of wait states for read and write operations</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t _flash_get_wait_state(struct _flash_device *const device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set the number of wait states for read and write operations.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] state The number of wait states</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_set_wait_state(struct _flash_device *const device, uint8_t state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Enable/disable Flash interrupt</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * param[in] device The pointer to Flash device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * param[in] type The type of interrupt to disable/enable if applicable</span><br><span style="color: hsl(120, 100%, 40%);">+ * param[in] state Enable or disable</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_set_irq_state(struct _flash_device *const device, const enum _flash_cb_type type, const bool state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Below RWW flash APIs are only available for device which has RWWEE</span><br><span style="color: hsl(120, 100%, 40%);">+ * flash array, such as SAM C20/C21/D21/L21/L22/R30/DA1/HA1 etc.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the RWWEE flash page size.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The flash page size</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _rww_flash_get_page_size(struct _flash_device *const device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the total page numbers of RWWEE flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The flash total page numbers</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _rww_flash_get_total_pages(struct _flash_device *const device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Reads a number of bytes in the internal RWWEE Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  src_addr      Source bytes address to read from flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buffer        Pointer to a buffer where the content</span><br><span style="color: hsl(120, 100%, 40%);">+ *                           of the read page will be stored</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  length        Number of bytes to read</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Read status, ERR_NONE for successful read.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _rww_flash_read(struct _flash_device *const device, const uint32_t src_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Writes a number of bytes in the internal RWWEE Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device         The pointer to FLASH device instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  dst_addr      Destination bytes address to write into flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  buffer        Pointer to buffer where the data to</span><br><span style="color: hsl(120, 100%, 40%);">+ *                           write is stored</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  length        Number of bytes to write</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Write status, ERR_NONE for successful write.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _rww_flash_write(struct _flash_device *const device, const uint32_t dst_addr, uint8_t *buffer, uint32_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**@}*/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* _HPL_FLASH_H_INCLUDED */</span><br><span>diff --git a/hal/include/hpl_user_area.h b/hal/include/hpl_user_area.h</span><br><span>new file mode 100644</span><br><span>index 0000000..1f14098</span><br><span>--- /dev/null</span><br><span>+++ b/hal/include/hpl_user_area.h</span><br><span>@@ -0,0 +1,123 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Special user data area access</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_start</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \page License</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Subject to your compliance with these terms, you may use Microchip</span><br><span style="color: hsl(120, 100%, 40%);">+ * software and any derivatives exclusively with Microchip products.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is your responsibility to comply with third party license terms applicable</span><br><span style="color: hsl(120, 100%, 40%);">+ * to your use of third party software (including open source software) that</span><br><span style="color: hsl(120, 100%, 40%);">+ * may accompany Microchip software.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,</span><br><span style="color: hsl(120, 100%, 40%);">+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL</span><br><span style="color: hsl(120, 100%, 40%);">+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT</span><br><span style="color: hsl(120, 100%, 40%);">+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY</span><br><span style="color: hsl(120, 100%, 40%);">+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_stop</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _HPL_USER_DATA_H_INCLUDED</span><br><span style="color: hsl(120, 100%, 40%);">+#define _HPL_USER_DATA_H_INCLUDED</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Read data from user data area</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The user data area could be the area that stores user data that is not erased</span><br><span style="color: hsl(120, 100%, 40%);">+ * with the flash contents, e.g.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * - NVM Software Calibration Area of SAM D/L/C family</span><br><span style="color: hsl(120, 100%, 40%);">+ * - User Signature of SAM E/S/V 70</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  base   The base address of the user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  offset The byte offset of the data to be read inside the area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buf    Pointer to buffer to place the read data</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  size   Size of data in number of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Operation status or bytes read.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_NONE Data read successfully</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_UNSUPPORTED_OP base address not in any supported user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_BAD_ADDRESS offset not in right area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_INVALID_ARG offset and size exceeds the right area</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _user_area_read(const void *base, const uint32_t offset, uint8_t *buf, const uint32_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Read no more than 32 bits data from user data area</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * When reading bits, the bitfield can cross 32-bis boundaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] base       The base address of the user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bit_offset Offset in number of bits</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] n_bits     Number of bits to read</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return data read, assert if anything wrong (address not in user area</span><br><span style="color: hsl(120, 100%, 40%);">+ *         offset, size error, etc.).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _user_area_read_bits(const void *base, const uint32_t bit_offset, const uint8_t n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Write data to user data area</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The user data area could be the area that stores user data that is not erased</span><br><span style="color: hsl(120, 100%, 40%);">+ * with the flash contents, e.g.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * - NVM Software Calibration Area of SAM D/L/C family</span><br><span style="color: hsl(120, 100%, 40%);">+ * - User Signature of SAM E/S/V 70</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * When assigned offset and size exceeds the data area, error is reported.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] base  The base address of the user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  offset The offset of the data to be written inside the area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  buf    Pointer to buffer to place the written data</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  size   Size of data in number of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Operation status or bytes writting.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_NONE Data written successfully</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_UNSUPPORTED_OP base address not in any supported user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_DENIED Security bit is set</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_BAD_ADDRESS offset not in right area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_INVALID_ARG offset and size exceeds the right area</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _user_area_write(void *base, const uint32_t offset, const uint8_t *buf, const uint32_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Write no more than 32 bits data to user data area</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * When writting bits, the bitfield can cross 32-bis boundaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] base       The base address of the user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  bit_offset Offset in number of bits</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  bits       The data content</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  n_bits     Number of bits to write</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Operation result</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_NONE Data written successfully</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_UNSUPPORTED_OP base address not in any supported user area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_DENIED Security bit is set</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_BAD_ADDRESS offset not in right area</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval ERR_INVALID_ARG offset and size exceeds the right area</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _user_area_write_bits(void *base, const uint32_t bit_offset, const uint32_t bits, const uint8_t n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __cplusplus</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* _HPL_USER_DATA_H_INCLUDED */</span><br><span>diff --git a/hal/src/hal_flash.c b/hal/src/hal_flash.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b1a58b7</span><br><span>--- /dev/null</span><br><span>+++ b/hal/src/hal_flash.c</span><br><span>@@ -0,0 +1,314 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Flash functionality implementation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_start</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \page License</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Subject to your compliance with these terms, you may use Microchip</span><br><span style="color: hsl(120, 100%, 40%);">+ * software and any derivatives exclusively with Microchip products.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is your responsibility to comply with third party license terms applicable</span><br><span style="color: hsl(120, 100%, 40%);">+ * to your use of third party software (including open source software) that</span><br><span style="color: hsl(120, 100%, 40%);">+ * may accompany Microchip software.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,</span><br><span style="color: hsl(120, 100%, 40%);">+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL</span><br><span style="color: hsl(120, 100%, 40%);">+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT</span><br><span style="color: hsl(120, 100%, 40%);">+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY</span><br><span style="color: hsl(120, 100%, 40%);">+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_stop</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "hal_flash.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include <utils_assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <hal_atomic.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Driver version</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define DRIVER_VERSION 0x00000001u</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void flash_ready(struct _flash_device *device);</span><br><span style="color: hsl(120, 100%, 40%);">+static void flash_error(struct _flash_device *device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t flash_is_address_aligned(struct flash_descriptor *flash, const uint32_t flash_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Initialize the FLASH HAL instance and hardware for callback mode.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_init(struct flash_descriptor *flash, void *const hw)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ASSERT(flash && hw);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = _flash_init(&flash->dev, hw);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   flash->dev.flash_cb.ready_cb = flash_ready;</span><br><span style="color: hsl(120, 100%, 40%);">+        flash->dev.flash_cb.error_cb = flash_error;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief  Deinitialize the FLASH HAL instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_deinit(struct flash_descriptor *flash)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     ASSERT(flash);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      _flash_deinit(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Reads a number of bytes to a page in the internal Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_read(struct flash_descriptor *flash, uint32_t src_addr, uint8_t *buffer, uint32_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        ASSERT(flash && buffer && length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t page_size   = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t total_pages = _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Check if the address is valid */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((src_addr > page_size * total_pages) || (src_addr + length > page_size * total_pages)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   _flash_read(&flash->dev, src_addr, buffer, length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Updates several bytes to the internal Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_write(struct flash_descriptor *flash, uint32_t dst_addr, uint8_t *buffer, uint32_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   ASSERT(flash && buffer && length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t page_size   = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t total_pages = _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Check if the address is valid */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((dst_addr > page_size * total_pages) || (dst_addr + length > page_size * total_pages)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (_flash_is_locked(&flash->dev, dst_addr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   _flash_write(&flash->dev, dst_addr, buffer, length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Appends a number of bytes to a page in the internal Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_append(struct flash_descriptor *flash, uint32_t dst_addr, uint8_t *buffer, uint32_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ASSERT(flash && buffer && length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t page_size   = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t total_pages = _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Check if the address is valid */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((dst_addr > page_size * total_pages) || (dst_addr + length > page_size * total_pages)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (_flash_is_locked(&flash->dev, dst_addr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   _flash_append(&flash->dev, dst_addr, buffer, length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute erase in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_erase(struct flash_descriptor *flash, const uint32_t dst_addr, const uint32_t page_nums)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     ASSERT(flash && page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t page_size   = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t total_pages = _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t  rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = flash_is_address_aligned(flash, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((page_nums > total_pages) || (dst_addr / page_size + page_nums > total_pages)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   _flash_erase(&flash->dev, dst_addr, page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Register a function as FLASH transfer completion callback</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_register_callback(struct flash_descriptor *flash, const enum flash_cb_type type, flash_cb_t func)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT(flash);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (type) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case FLASH_CB_READY:</span><br><span style="color: hsl(120, 100%, 40%);">+          flash->callbacks.cb_ready = func;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case FLASH_CB_ERROR:</span><br><span style="color: hsl(120, 100%, 40%);">+          flash->callbacks.cb_error = func;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   _flash_set_irq_state(&flash->dev, (enum _flash_cb_type)type, NULL != func);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute lock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_lock(struct flash_descriptor *flash, const uint32_t dst_addr, const uint32_t page_nums)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       ASSERT(flash && page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t page_size   = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t total_pages = _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t  rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = flash_is_address_aligned(flash, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((page_nums > total_pages) || (dst_addr / page_size + page_nums > total_pages)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return _flash_lock(&flash->dev, dst_addr, page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute unlock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t flash_unlock(struct flash_descriptor *flash, const uint32_t dst_addr, const uint32_t page_nums)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       ASSERT(flash && page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t page_size   = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t total_pages = _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t  rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = flash_is_address_aligned(flash, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((page_nums > total_pages) || (dst_addr / page_size + page_nums > total_pages)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return _flash_unlock(&flash->dev, dst_addr, page_nums);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the flash page size.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t flash_get_page_size(struct flash_descriptor *flash)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ASSERT(flash);</span><br><span style="color: hsl(120, 100%, 40%);">+        return _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the numbers of flash page.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t flash_get_total_pages(struct flash_descriptor *flash)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  ASSERT(flash);</span><br><span style="color: hsl(120, 100%, 40%);">+        return _flash_get_total_pages(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Retrieve the current driver version</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t flash_get_version(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return DRIVER_VERSION;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal check the address whether it is aligned</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in, out] flash        Pointer to the HAL FLASH instance.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  flash_addr       address to be check in flash</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return whether it is valid</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \retval 0 Valid.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \retval -1 Error, invalid.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t flash_is_address_aligned(struct flash_descriptor *flash, const uint32_t flash_addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        ASSERT(flash);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t page_size = _flash_get_page_size(&flash->dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Check if the read address not aligned to the start of a page */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (flash_addr & (page_size - 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal Ready for a new flash command</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device The pointer to flash device structure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void flash_ready(struct _flash_device *device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct flash_descriptor *const descr = CONTAINER_OF(device, struct flash_descriptor, dev);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (descr->callbacks.cb_ready) {</span><br><span style="color: hsl(120, 100%, 40%);">+           descr->callbacks.cb_ready(descr);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal Error occurs in flash command</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] device The pointer to flash device structure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void flash_error(struct _flash_device *device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct flash_descriptor *const descr = CONTAINER_OF(device, struct flash_descriptor, dev);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (descr->callbacks.cb_error) {</span><br><span style="color: hsl(120, 100%, 40%);">+           descr->callbacks.cb_error(descr);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/hpl/nvmctrl/hpl_nvmctrl.c b/hpl/nvmctrl/hpl_nvmctrl.c</span><br><span>new file mode 100644</span><br><span>index 0000000..63f6145</span><br><span>--- /dev/null</span><br><span>+++ b/hpl/nvmctrl/hpl_nvmctrl.c</span><br><span>@@ -0,0 +1,695 @@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Non-Volatile Memory Controller</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_start</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \page License</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Subject to your compliance with these terms, you may use Microchip</span><br><span style="color: hsl(120, 100%, 40%);">+ * software and any derivatives exclusively with Microchip products.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is your responsibility to comply with third party license terms applicable</span><br><span style="color: hsl(120, 100%, 40%);">+ * to your use of third party software (including open source software) that</span><br><span style="color: hsl(120, 100%, 40%);">+ * may accompany Microchip software.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,</span><br><span style="color: hsl(120, 100%, 40%);">+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL</span><br><span style="color: hsl(120, 100%, 40%);">+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT</span><br><span style="color: hsl(120, 100%, 40%);">+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY</span><br><span style="color: hsl(120, 100%, 40%);">+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,</span><br><span style="color: hsl(120, 100%, 40%);">+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \asf_license_stop</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <hpl_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <hpl_user_area.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <utils_assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <hpl_nvmctrl_config.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define NVM_MEMORY ((volatile uint32_t *)FLASH_ADDR)</span><br><span style="color: hsl(120, 100%, 40%);">+#define NVMCTRL_BLOCK_PAGES (NVMCTRL_BLOCK_SIZE / NVMCTRL_PAGE_SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+#define NVMCTRL_REGIONS_NUM 32</span><br><span style="color: hsl(120, 100%, 40%);">+#define NVMCTRL_INTFLAG_ERR                                                                                            \</span><br><span style="color: hsl(120, 100%, 40%);">+      (NVMCTRL_INTFLAG_ADDRE | NVMCTRL_INTFLAG_PROGE | NVMCTRL_INTFLAG_LOCKE | NVMCTRL_INTFLAG_ECCSE                     \</span><br><span style="color: hsl(120, 100%, 40%);">+   | NVMCTRL_INTFLAG_NVME | NVMCTRL_INTFLAG_SEESOVF)</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief NVM configuration type</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct nvm_configuration {</span><br><span style="color: hsl(120, 100%, 40%);">+    hri_nvmctrl_ctrlb_reg_t ctrla; /*!< Control B Register */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Array of NVM configurations</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct nvm_configuration _nvm</span><br><span style="color: hsl(120, 100%, 40%);">+    = {(CONF_NVM_CACHE0 << NVMCTRL_CTRLA_CACHEDIS0_Pos) | (CONF_NVM_CACHE1 << NVMCTRL_CTRLA_CACHEDIS1_Pos)</span><br><span style="color: hsl(120, 100%, 40%);">+       | (NVMCTRL_CTRLA_PRM(CONF_NVM_SLEEPPRM))};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!< Pointer to hpl device */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct _flash_device *_nvm_dev = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void _flash_erase_block(void *const hw, const uint32_t dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+static void _flash_program(void *const hw, const uint32_t dst_addr, const uint8_t *buffer, const uint16_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Initialize NVM</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _flash_init(struct _flash_device *const device, void *const hw)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t ctrla;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ASSERT(device && (hw == NVMCTRL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  device->hw = hw;</span><br><span style="color: hsl(120, 100%, 40%);">+   ctrla      = hri_nvmctrl_read_CTRLA_reg(hw);</span><br><span style="color: hsl(120, 100%, 40%);">+  ctrla &= ~(NVMCTRL_CTRLA_CACHEDIS0 | NVMCTRL_CTRLA_CACHEDIS1 | NVMCTRL_CTRLA_PRM_Msk);</span><br><span style="color: hsl(120, 100%, 40%);">+    ctrla |= _nvm.ctrla;</span><br><span style="color: hsl(120, 100%, 40%);">+  hri_nvmctrl_write_CTRLA_reg(hw, ctrla);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     _nvm_dev = device;</span><br><span style="color: hsl(120, 100%, 40%);">+    NVIC_DisableIRQ(NVMCTRL_0_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+      NVIC_DisableIRQ(NVMCTRL_1_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+      NVIC_ClearPendingIRQ(NVMCTRL_0_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+ NVIC_ClearPendingIRQ(NVMCTRL_1_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+ NVIC_EnableIRQ(NVMCTRL_0_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+       NVIC_EnableIRQ(NVMCTRL_1_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief De-initialize NVM</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_deinit(struct _flash_device *const device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       device->hw = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ NVIC_DisableIRQ(NVMCTRL_0_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+      NVIC_DisableIRQ(NVMCTRL_1_IRQn);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the flash page size.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _flash_get_page_size(struct _flash_device *const device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     (void)device;</span><br><span style="color: hsl(120, 100%, 40%);">+ return (uint32_t)NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the numbers of flash page.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _flash_get_total_pages(struct _flash_device *const device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  (void)device;</span><br><span style="color: hsl(120, 100%, 40%);">+ return (uint32_t)hri_nvmctrl_read_PARAM_NVMP_bf(device->hw);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the number of wait states for read and write operations.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t _flash_get_wait_state(struct _flash_device *const device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return hri_nvmctrl_get_CTRLA_reg(device->hw, NVMCTRL_CTRLA_RWS_Msk);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set the number of wait states for read and write operations.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_set_wait_state(struct _flash_device *const device, uint8_t state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      hri_nvmctrl_write_CTRLA_RWS_bf(device->hw, state);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Reads a number of bytes to a page in the internal Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_read(struct _flash_device *const device, const uint32_t src_addr, uint8_t *buffer, uint32_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *nvm_addr = (uint8_t *)NVM_MEMORY;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if the module is busy */</span><br><span style="color: hsl(120, 100%, 40%);">+     while (!hri_nvmctrl_get_STATUS_READY_bit(device->hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < length; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             buffer[i] = nvm_addr[src_addr + i];</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Writes a number of bytes to a page in the internal Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_write(struct _flash_device *const device, const uint32_t dst_addr, uint8_t *buffer, uint32_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t  tmp_buffer[NVMCTRL_BLOCK_PAGES][NVMCTRL_PAGE_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t block_start_addr, block_end_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t i, j, k;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t wr_start_addr = dst_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  do {</span><br><span style="color: hsl(120, 100%, 40%);">+          block_start_addr = wr_start_addr & ~(NVMCTRL_BLOCK_SIZE - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+             block_end_addr   = block_start_addr + NVMCTRL_BLOCK_SIZE - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* store the erase data into temp buffer before write */</span><br><span style="color: hsl(120, 100%, 40%);">+              for (i = 0; i < NVMCTRL_BLOCK_PAGES; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        _flash_read(device, block_start_addr + i * NVMCTRL_PAGE_SIZE, tmp_buffer[i], NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* temp buffer update */</span><br><span style="color: hsl(120, 100%, 40%);">+              j = (wr_start_addr - block_start_addr) / NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+           k = wr_start_addr - block_start_addr - j * NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+         while ((wr_start_addr <= block_end_addr) && (length > 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     tmp_buffer[j][k] = *buffer;</span><br><span style="color: hsl(120, 100%, 40%);">+                   k                = (k + 1) % NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (0 == k) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         j++;</span><br><span style="color: hsl(120, 100%, 40%);">+                  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   wr_start_addr++;</span><br><span style="color: hsl(120, 100%, 40%);">+                      buffer++;</span><br><span style="color: hsl(120, 100%, 40%);">+                     length--;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* erase row before write */</span><br><span style="color: hsl(120, 100%, 40%);">+          _flash_erase_block(device->hw, block_start_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* write buffer to flash */</span><br><span style="color: hsl(120, 100%, 40%);">+           for (i = 0; i < NVMCTRL_BLOCK_PAGES; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        _flash_program(device->hw, block_start_addr + i * NVMCTRL_PAGE_SIZE, tmp_buffer[i], NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     } while (block_end_addr < (wr_start_addr + length - 1));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Appends a number of bytes in the internal Flash.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_append(struct _flash_device *const device, const uint32_t dst_addr, uint8_t *buffer, uint32_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t page_start_addr = dst_addr & ~(NVMCTRL_PAGE_SIZE - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (dst_addr != page_start_addr) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Need to write some data to the end of a page */</span><br><span style="color: hsl(120, 100%, 40%);">+            size = min(length, NVMCTRL_PAGE_SIZE - (dst_addr - page_start_addr));</span><br><span style="color: hsl(120, 100%, 40%);">+         _flash_program(device->hw, dst_addr, buffer, size);</span><br><span style="color: hsl(120, 100%, 40%);">+                page_start_addr += NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+         offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (offset < length) {</span><br><span style="color: hsl(120, 100%, 40%);">+          size = min(length - offset, NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+               _flash_program(device->hw, page_start_addr, buffer + offset, size);</span><br><span style="color: hsl(120, 100%, 40%);">+                page_start_addr += NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+         offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute erase in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_erase(struct _flash_device *const device, uint32_t dst_addr, uint32_t page_nums)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t  tmp_buffer[NVMCTRL_PAGE_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t block_start_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ block_start_addr = dst_addr & ~(NVMCTRL_BLOCK_SIZE - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        memset(tmp_buffer, 0xFF, NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* when address is not aligned with block start address */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (dst_addr != block_start_addr) {</span><br><span style="color: hsl(120, 100%, 40%);">+           block_start_addr += NVMCTRL_BLOCK_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+               for (i = 0; i < NVMCTRL_BLOCK_PAGES - 1; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    _flash_write(device, dst_addr, tmp_buffer, NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (--page_nums == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               return;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   dst_addr += NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (dst_addr == block_start_addr) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (page_nums >= NVMCTRL_BLOCK_PAGES) {</span><br><span style="color: hsl(120, 100%, 40%);">+         _flash_erase_block(device->hw, block_start_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+          block_start_addr += NVMCTRL_BLOCK_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+               page_nums -= NVMCTRL_BLOCK_PAGES;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (page_nums != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+         for (i = 0; i < page_nums; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  _flash_write(device, block_start_addr, tmp_buffer, NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+                        block_start_addr += NVMCTRL_PAGE_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute lock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _flash_lock(struct _flash_device *const device, const uint32_t dst_addr, uint32_t page_nums)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t region_pages;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t block_start_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  region_pages     = (uint32_t)FLASH_SIZE / (NVMCTRL_REGIONS_NUM * NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+  block_start_addr = dst_addr & ~(NVMCTRL_BLOCK_SIZE - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((page_nums != region_pages) || (dst_addr != block_start_addr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!hri_nvmctrl_get_STATUS_READY_bit(device->hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   hri_nvmctrl_write_ADDR_reg(device->hw, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+  hri_nvmctrl_write_CTRLB_reg(device->hw, NVMCTRL_CTRLB_CMD_LR | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return (int32_t)FLASH_SIZE / (NVMCTRL_REGIONS_NUM * NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute unlock in the internal flash</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _flash_unlock(struct _flash_device *const device, const uint32_t dst_addr, uint32_t page_nums)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t region_pages;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t block_start_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  region_pages     = (uint32_t)FLASH_SIZE / (NVMCTRL_REGIONS_NUM * NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+  block_start_addr = dst_addr & ~(NVMCTRL_BLOCK_SIZE - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((page_nums != region_pages) || (dst_addr != block_start_addr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!hri_nvmctrl_get_STATUS_READY_bit(device->hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   hri_nvmctrl_write_ADDR_reg(device->hw, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+  hri_nvmctrl_write_CTRLB_reg(device->hw, NVMCTRL_CTRLB_CMD_UR | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return (int32_t)FLASH_SIZE / (NVMCTRL_REGIONS_NUM * NVMCTRL_PAGE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief check whether the region which is pointed by address</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+bool _flash_is_locked(struct _flash_device *const device, const uint32_t dst_addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t region_id;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Get region for given page */</span><br><span style="color: hsl(120, 100%, 40%);">+       region_id = dst_addr / (FLASH_SIZE / NVMCTRL_REGIONS_NUM);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return !(hri_nvmctrl_get_RUNLOCK_reg(device->hw, 1 << region_id));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Enable/disable Flash interrupt</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void _flash_set_irq_state(struct _flash_device *const device, const enum _flash_cb_type type, const bool state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT(device);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (FLASH_DEVICE_CB_READY == type) {</span><br><span style="color: hsl(120, 100%, 40%);">+          hri_nvmctrl_write_INTEN_DONE_bit(device->hw, state);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (FLASH_DEVICE_CB_ERROR == type) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (state) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  hri_nvmctrl_write_INTEN_reg(device->hw, NVMCTRL_INTFLAG_ERR);</span><br><span style="color: hsl(120, 100%, 40%);">+              } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      hri_nvmctrl_clear_INTEN_reg(device->hw, NVMCTRL_INTFLAG_ERR);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal   erase a row in flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  hw            The pointer to hardware instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  dst_addr      Destination page address to erase</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void _flash_erase_block(void *const hw, const uint32_t dst_addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Set address and command */</span><br><span style="color: hsl(120, 100%, 40%);">+ hri_nvmctrl_write_ADDR_reg(hw, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+     hri_nvmctrl_write_CTRLB_reg(hw, NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal   write a page in flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  hw            The pointer to hardware instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  dst_addr      Destination page address to write</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in]  buffer        Pointer to buffer where the data to</span><br><span style="color: hsl(120, 100%, 40%);">+ *                           write is stored</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] size           The size of data to write to a page</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void _flash_program(void *const hw, const uint32_t dst_addr, const uint8_t *buffer, const uint16_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t *ptr_read    = (uint32_t *)buffer;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t  nvm_address = dst_addr / 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t  i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   hri_nvmctrl_write_CTRLB_reg(hw, NVMCTRL_CTRLB_CMD_PBC | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Writes to the page buffer must be 32 bits, perform manual copy</span><br><span style="color: hsl(120, 100%, 40%);">+      * to ensure alignment */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < size; i += 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+            NVM_MEMORY[nvm_address++] = *ptr_read;</span><br><span style="color: hsl(120, 100%, 40%);">+                ptr_read++;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   hri_nvmctrl_write_ADDR_reg(hw, dst_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+     hri_nvmctrl_write_CTRLB_reg(hw, NVMCTRL_CTRLB_CMD_WP | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal NVM interrupt handler</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] p The pointer to interrupt parameter</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void _nvm_interrupt_handler(struct _flash_device *device)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      void *const hw = device->hw;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (hri_nvmctrl_get_INTFLAG_DONE_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           hri_nvmctrl_clear_INTFLAG_DONE_bit(hw);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             if (NULL != device->flash_cb.ready_cb) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   device->flash_cb.ready_cb(device);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (hri_nvmctrl_read_INTFLAG_reg(hw) && ~NVMCTRL_INTFLAG_ERR) {</span><br><span style="color: hsl(120, 100%, 40%);">+                hri_nvmctrl_clear_INTFLAG_reg(hw, NVMCTRL_INTFLAG_ERR);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             if (NULL != device->flash_cb.error_cb) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   device->flash_cb.error_cb(device);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal NVM 0 interrupt handler</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void NVMCTRL_0_Handler(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       _nvm_interrupt_handler(_nvm_dev);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal NVM 1 interrupt handler</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void NVMCTRL_1_Handler(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       _nvm_interrupt_handler(_nvm_dev);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+   The NVM User Row contains calibration data that are automatically read at device</span><br><span style="color: hsl(120, 100%, 40%);">+   power on.</span><br><span style="color: hsl(120, 100%, 40%);">+   The NVM User Row can be read at address 0x804000.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   The first eight 32-bit words (32 Bytes) of the Non Volatile Memory (NVM) User</span><br><span style="color: hsl(120, 100%, 40%);">+   Page contain calibration data that are automatically read at device power-on.</span><br><span style="color: hsl(120, 100%, 40%);">+   The remaining 480 Bytes can be used for storing custom parameters.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _NVM_USER_ROW_BASE</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_USER_ROW_BASE 0x804000</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_USER_ROW_N_BITS 4096</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_USER_ROW_N_BYTES (_NVM_USER_ROW_N_BITS / 8)</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_USER_ROW_END (((uint8_t *)_NVM_USER_ROW_BASE) + _NVM_USER_ROW_N_BYTES - 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define _IS_NVM_USER_ROW(b)                                                                                            \</span><br><span style="color: hsl(120, 100%, 40%);">+        (((uint8_t *)(b) >= (uint8_t *)(_NVM_USER_ROW_BASE)) && ((uint8_t *)(b) <= (uint8_t *)(_NVM_USER_ROW_END)))</span><br><span style="color: hsl(120, 100%, 40%);">+#define _IN_NVM_USER_ROW(b, o) (((uint8_t *)(b) + (o)) <= (uint8_t *)(_NVM_USER_ROW_END))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+   The NVM Software Calibration Area can be read at address 0x00800080.</span><br><span style="color: hsl(120, 100%, 40%);">+   The NVM Software Calibration Area can not be written.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _NVM_SW_CALIB_AREA_BASE</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_SW_CALIB_AREA_BASE 0x00800080</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_SW_CALIB_AREA_N_BITS 45</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_SW_CALIB_AREA_N_BYTES (_NVM_SW_CALIB_AREA_N_BITS / 8)</span><br><span style="color: hsl(120, 100%, 40%);">+#define _NVM_SW_CALIB_AREA_END (((uint8_t *)_NVM_SW_CALIB_AREA_BASE) + _NVM_SW_CALIB_AREA_N_BYTES - 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define _IS_NVM_SW_CALIB_AREA(b)                                                                                       \</span><br><span style="color: hsl(120, 100%, 40%);">+        (((uint8_t *)(b) >= (uint8_t *)_NVM_SW_CALIB_AREA_BASE) && ((uint8_t *)(b) <= (uint8_t *)_NVM_SW_CALIB_AREA_END))</span><br><span style="color: hsl(120, 100%, 40%);">+#define _IN_NVM_SW_CALIB_AREA(b, o) (((uint8_t *)(b) + (o)) <= (uint8_t *)(_NVM_SW_CALIB_AREA_END))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal Read left aligned data bits</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] base       Base address for the data</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bit_offset Offset for the bitfield start</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] n_bits     Number of bits in the bitfield</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint32_t _user_area_read_l32_bits(const volatile uint32_t *base, const uint32_t bit_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                const uint8_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return base[bit_offset >> 5] & ((1 << n_bits) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal Read right aligned data bits</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] base       Base address for the data</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bit_offset Offset for the bitfield start</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] n_bits     Number of bits in the bitfield</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint32_t _user_area_read_r32_bits(const volatile uint32_t *base, const uint32_t bit_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                const uint8_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return (base[bit_offset >> 5] >> (bit_offset & 0x1F)) & ((1 << n_bits) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _user_area_read(const void *base, const uint32_t offset, uint8_t *buf, uint32_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ASSERT(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /** Parameter check. */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (_IS_NVM_USER_ROW(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!_IN_NVM_USER_ROW(base, offset)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Cut off if request too many bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!_IN_NVM_USER_ROW(base, offset + size - 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (_IS_NVM_SW_CALIB_AREA(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!_IN_NVM_SW_CALIB_AREA(base, offset)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Cut off if request too many bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!_IN_NVM_SW_CALIB_AREA(base, offset + size - 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_UNSUPPORTED_OP;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Copy data */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(buf, ((uint8_t *)base) + offset, size);</span><br><span style="color: hsl(120, 100%, 40%);">+        return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t _user_area_read_bits(const void *base, const uint32_t bit_offset, const uint8_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    volatile uint32_t *mem_base = (volatile uint32_t *)base;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t           l_off, l_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t           r_off, r_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /** Parameter check. */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (_IS_NVM_USER_ROW(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ASSERT(_IN_NVM_USER_ROW(base, bit_offset >> 3) && _IN_NVM_USER_ROW(base, (bit_offset + n_bits - 1) >> 3));</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (_IS_NVM_SW_CALIB_AREA(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ASSERT(_IN_NVM_SW_CALIB_AREA(base, bit_offset >> 3)</span><br><span style="color: hsl(120, 100%, 40%);">+                    && _IN_NVM_SW_CALIB_AREA(base, (bit_offset + n_bits - 1) >> 3));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ASSERT(false);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Since the bitfield can cross 32-bits boundaries,</span><br><span style="color: hsl(120, 100%, 40%);">+    * left and right bits are read from 32-bit aligned address</span><br><span style="color: hsl(120, 100%, 40%);">+    * and then combined together. */</span><br><span style="color: hsl(120, 100%, 40%);">+     l_off  = bit_offset & (~(32 - 1));</span><br><span style="color: hsl(120, 100%, 40%);">+        r_off  = l_off + 32;</span><br><span style="color: hsl(120, 100%, 40%);">+  l_bits = 32 - (bit_offset & (32 - 1));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (n_bits > l_bits) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r_bits = n_bits - l_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              l_bits = n_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+              r_bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return _user_area_read_r32_bits(mem_base, bit_offset, l_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+        + (_user_area_read_l32_bits(mem_base, r_off, r_bits) << l_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** \internal Write 4096-bit user row</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] _row Pointer to 4096-bit user row data.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int32_t _user_row_write_exec(const uint32_t *_row)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  Nvmctrl *hw    = NVMCTRL;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t ctrla = hri_nvmctrl_read_CTRLA_reg(NVMCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Denied if Security Bit is set */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (DSU->STATUSB.bit.PROT) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Do Save */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* - Prepare. */</span><br><span style="color: hsl(120, 100%, 40%);">+      while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     hri_nvmctrl_clear_CTRLA_WMODE_bf(NVMCTRL, NVMCTRL_CTRLA_WMODE_Msk);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* - Erase AUX row. */</span><br><span style="color: hsl(120, 100%, 40%);">+        hri_nvmctrl_write_ADDR_reg(hw, (hri_nvmctrl_addr_reg_t)_NVM_USER_ROW_BASE);</span><br><span style="color: hsl(120, 100%, 40%);">+   hri_nvmctrl_write_CTRLB_reg(hw, NVMCTRL_CTRLB_CMD_EP | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+      while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < 32; i++) { /* 32 Quad words for User row: 32 * (4 bytes * 4) = 512 bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+                /* - Page buffer clear & write. */</span><br><span style="color: hsl(120, 100%, 40%);">+                hri_nvmctrl_write_CTRLB_reg(hw, NVMCTRL_CTRLB_CMD_PBC | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+             while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             *(((uint32_t *)NVMCTRL_USER) + i * 4)     = _row[i * 4];</span><br><span style="color: hsl(120, 100%, 40%);">+              *(((uint32_t *)NVMCTRL_USER) + i * 4 + 1) = _row[i * 4 + 1];</span><br><span style="color: hsl(120, 100%, 40%);">+          *(((uint32_t *)NVMCTRL_USER) + i * 4 + 2) = _row[i * 4 + 2];</span><br><span style="color: hsl(120, 100%, 40%);">+          *(((uint32_t *)NVMCTRL_USER) + i * 4 + 3) = _row[i * 4 + 3];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* - Write AUX row. */</span><br><span style="color: hsl(120, 100%, 40%);">+                hri_nvmctrl_write_ADDR_reg(hw, (hri_nvmctrl_addr_reg_t)(_NVM_USER_ROW_BASE + i * 16));</span><br><span style="color: hsl(120, 100%, 40%);">+                hri_nvmctrl_write_CTRLB_reg(hw, NVMCTRL_CTRLB_CMD_WQW | NVMCTRL_CTRLB_CMDEX_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+             while (!hri_nvmctrl_get_STATUS_READY_bit(hw)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* Wait until this module isn't busy */</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Restore CTRLA */</span><br><span style="color: hsl(120, 100%, 40%);">+   hri_nvmctrl_write_CTRLA_reg(NVMCTRL, ctrla);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return ERR_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _user_area_write(void *base, const uint32_t offset, const uint8_t *buf, const uint32_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t _row[NVMCTRL_PAGE_SIZE / 4]; /* Copy of user row. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /** Parameter check. */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (_IS_NVM_USER_ROW(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!_IN_NVM_USER_ROW(base, offset)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+               } else if (!_IN_NVM_USER_ROW(base, offset + size - 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (_IS_NVM_SW_CALIB_AREA(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_UNSUPPORTED_OP;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(_row, base, NVMCTRL_PAGE_SIZE);       /* Store previous data. */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy((uint8_t *)_row + offset, buf, size); /* Modify with buf data. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return _user_row_write_exec(_row);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t _user_area_write_bits(void *base, const uint32_t bit_offset, const uint32_t bits, const uint8_t n_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t _row[NVMCTRL_PAGE_SIZE / 4]; /* Copy of user row. */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t l_off, l_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t r_off, r_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /** Parameter check. */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (_IS_NVM_USER_ROW(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!_IN_NVM_USER_ROW(base, bit_offset >> 3)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 return ERR_BAD_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+               } else if (!_IN_NVM_USER_ROW(base, (bit_offset + n_bits - 1) >> 3)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   return ERR_INVALID_ARG;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (_IS_NVM_SW_CALIB_AREA(base)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return ERR_DENIED;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERR_UNSUPPORTED_OP;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Since the bitfield can cross 32-bits boundaries,</span><br><span style="color: hsl(120, 100%, 40%);">+    * left and right bits are splitted for 32-bit aligned address</span><br><span style="color: hsl(120, 100%, 40%);">+         * and then saved. */</span><br><span style="color: hsl(120, 100%, 40%);">+ l_off  = bit_offset & (~(32 - 1));</span><br><span style="color: hsl(120, 100%, 40%);">+        r_off  = l_off + 32;</span><br><span style="color: hsl(120, 100%, 40%);">+  l_bits = 32 - (bit_offset & (32 - 1));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (n_bits > l_bits) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r_bits = n_bits - l_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              l_bits = n_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+              r_bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(_row, base, NVMCTRL_PAGE_SIZE); /* Store previous data. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (l_bits) {</span><br><span style="color: hsl(120, 100%, 40%);">+         uint32_t l_mask = ((1 << l_bits) - 1) << (bit_offset & (32 - 1));</span><br><span style="color: hsl(120, 100%, 40%);">+             _row[bit_offset >> 5] &= ~l_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+           _row[bit_offset >> 5] |= (bits << (bit_offset & (32 - 1))) & l_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (r_bits) {</span><br><span style="color: hsl(120, 100%, 40%);">+         uint32_t r_mask = (1 << r_bits) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            _row[r_off >> 5] &= ~r_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+                _row[r_off >> 5] |= bits >> l_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return _user_row_write_exec(_row);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12501">change 12501</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/12501"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-asf4-dfu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I5eccb37da64c7def7b99418773d09b6d98664432 </div>
<div style="display:none"> Gerrit-Change-Number: 12501 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Kévin Redon <kredon@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>