lpcmanager

Parents e42521549e20
Children 62e8bfd13812
Some cleanup in LPCArch to prevent confusion when transfering program to a particular target
--- a/LPCArch.py Tue Feb 05 13:33:17 2019 +0100
+++ b/LPCArch.py Tue Feb 19 11:35:41 2019 +0100
@@ -1,9 +1,9 @@
#!/usr/bin/env python
# XXX Where is MC8 ?
-PLC_GOT_module = ['GOT', 'GOT_111', 'GOT_131']
-PLC_MC9_module = ['MC9']
-PLC_module = PLC_MC9_module + PLC_GOT_module
+PLC_GOT_modules = ['GOT', 'GOT_111', 'GOT_131']
+PLC_MC9_modules = ['MC9', 'MW1']
+SOM28_modules = PLC_MC9_modules + PLC_GOT_modules
arch = None
--- a/LPCBus.py Tue Feb 05 13:33:17 2019 +0100
+++ b/LPCBus.py Tue Feb 19 11:35:41 2019 +0100
@@ -3,9 +3,9 @@
modpath = os.path.split(__file__)[0]
-from LPCArch import GetLPCArch, PLC_module
+from LPCArch import GetLPCArch, SOM28_modules
arch = GetLPCArch()
-if arch in PLC_module:
+if arch in SOM28_modules:
bus_template_name = "MC9"
else:
bus_template_name = arch
--- a/LPCExtension.py Tue Feb 05 13:33:17 2019 +0100
+++ b/LPCExtension.py Tue Feb 19 11:35:41 2019 +0100
@@ -8,7 +8,7 @@
import features
from POULibrary import SimplePOULibraryFactory
-from LPCArch import arch, PLC_MC9_module, PLC_GOT_module
+from LPCArch import arch, PLC_MC9_modules, PLC_GOT_modules
# _lpcmanager_path, arch, etc are defined here because
# globals() of LPCManager.py are passed to extentions
@@ -18,10 +18,10 @@
def _poulibpath(name):
return os.path.join(_lpcmanager_path, 'Pous', "pous"+name+".xml")
-if arch in PLC_MC9_module:
+if arch in PLC_MC9_modules:
features.libraries += [('Python', 'py_ext.PythonLibrary', True),
('RTC', SimplePOULibraryFactory(_poulibpath("RTC")), True)]
-elif arch in PLC_GOT_module:
+elif arch in PLC_GOT_modules:
features.libraries += [('Python', 'py_ext.PythonLibrary', True),
('RTC', SimplePOULibraryFactory(_poulibpath("RTC")), True),
('GOT', SimplePOULibraryFactory(_poulibpath("GOT")), True)]
@@ -66,15 +66,20 @@
import targets
from LPCtarget import LPC_target
-targets.targets["LPC"] = {"xsd": os.path.join(_lpcmanager_path, "LPCtarget", "XSD"),
- "class": lambda: LPC_target,
- "code": {os.path.join(_lpcmanager_path, "LPCtarget", "plc_LPC_main.c")}}
-targets.toolchains["makefile"] = os.path.join(_lpcmanager_path, "LPCtarget", "XSD_toolchain_makefile")
-targets.targets["MC9"] = {"xsd": os.path.join(_lpcmanager_path, "MC9target", "XSD"),
- "class": targets.targets["Xenomai"]["class"],
- "code": {"plc_MC9_main.c": targets.targets["Xenomai"]["code"]["plc_Xenomai_main.c"],
- "plc_MC9_main_retain.c": os.path.join(_lpcmanager_path,
- "MC9target", "plc_MC9_main_retain.c")}}
+# targets.targets["LPC"] = {"xsd": os.path.join(_lpcmanager_path, "LPCtarget", "XSD"),
+# "class": lambda: LPC_target,
+# "code": {os.path.join(_lpcmanager_path, "LPCtarget", "plc_LPC_main.c")}}
+# targets.toolchains["makefile"] = os.path.join(_lpcmanager_path, "LPCtarget", "XSD_toolchain_makefile")
+
+# for arch in SOM28_modules:
+
+targets.targets = {arch : {
+ "xsd": os.path.join(_lpcmanager_path, "SOM28target", "XSD"),
+ "class": targets.targets["Xenomai"]["class"],
+ "code": {"plc_SOM28_main.c": targets.targets["Xenomai"]["code"]["plc_Xenomai_main.c"],
+ "plc_SOM28_main_retain.c": os.path.join(_lpcmanager_path,
+ "SOM28target",
+ "plc_SOM28_main_retain.c")}}}
#
# --------- Custom columns function Extension ------------
--- a/LPCManager.py Tue Feb 05 13:33:17 2019 +0100
+++ b/LPCManager.py Tue Feb 19 11:35:41 2019 +0100
@@ -22,7 +22,7 @@
# Path of directory containing current python file
_lpcmanager_path = os.path.split(__file__)[0]
-from LPCArch import PLC_module, SetLPCArch
+from LPCArch import SetLPCArch
from Beremiz import BeremizIDELauncher
class LPCManagerLauncher(BeremizIDELauncher):
--- a/LPCProjectController.py Tue Feb 05 13:33:17 2019 +0100
+++ b/LPCProjectController.py Tue Feb 19 11:35:41 2019 +0100
@@ -6,12 +6,12 @@
import wx
from ProjectController import ProjectController
-from LPCArch import PLC_module
from FirmwareUpdateDialog import FirmwareUpdateDialog
from HostFirmwareUpdater import HostFirmwareUpdater
from plcopen.types_enums import ComputeConfigurationResourceName
+from LPCArch import GetLPCArch
LPCStatusMethods = [
{"bitmap": "UpdateFw",
@@ -86,6 +86,16 @@
self.xEyeExport()
return result
+ def _Transfer(self):
+ if not self._connector.CheckProductID(GetLPCArch().lower()):
+ message = (_("Product ID doesn't match selected target type.\n"))
+ dialog = wx.MessageDialog(
+ self.AppFrame, message, _("Error"), wx.OK | wx.ICON_ERROR)
+ dialog.ShowModal()
+ return False
+
+ return ProjectController._Transfer(self)
+
def SetProjectName(self, name):
return self.Project.setname(name)
@@ -147,9 +157,7 @@
self.RefreshConfNodesBlockLists()
- # FIXME XXX
- if self.arch in PLC_module:
- self.SetParamsAttribute('BeremizRoot.TargetType', 'MC9')
+ self.SetParamsAttribute('BeremizRoot.TargetType', self.arch)
return None
--- a/MC9target/XSD Tue Feb 05 13:33:17 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-<xsd:element name="MC9">
- <xsd:complexType>
- <xsd:attribute name="Compiler" type="xsd:string" use="optional" default="arm-unknown-linux-gnueabi-gcc"/>
- <xsd:attribute name="CFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-linux-gnueabi-apf28 -DHAVE_RETAIN -pipe -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-variable -I../arm-linux-gnueabi-apf28/usr/include/xenomai/cobalt -I../arm-linux-gnueabi-apf28/usr/include/xenomai -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I../arm-linux-gnueabi-apf28/usr/include/xenomai/alchemy -D__COBALT_WRAP__ "/>
- <xsd:attribute name="Linker" type="xsd:string" use="optional" default="arm-unknown-linux-gnueabi-gcc"/>
- <xsd:attribute name="LDFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-linux-gnueabi-apf28 -lpthread -Wl,--no-as-needed -Wl,@../arm-linux-gnueabi-apf28/usr/lib/cobalt.wrappers -Wl,@../arm-linux-gnueabi-apf28/usr/lib/modechk.wrappers -lalchemy -lcopperplate -L../arm-linux-gnueabi-apf28/usr/lib -lcobalt -lmodechk -lpthread -lrt "/>
- <xsd:attribute name="XenoConfig" type="xsd:string" use="optional"/>
- </xsd:complexType>
-</xsd:element>
--- a/MC9target/plc_MC9_main_retain.c Tue Feb 05 13:33:17 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-
-#include <alchemy/event.h>
-#include <alchemy/mutex.h>
-#include <rtdm/rtdm.h>
-#include <rtdm/spi_apf28_rtdm_ioctl.h>
-#include <xenomai/init.h>
-
-
-/* SPI configurable parameters */
-/* --------------------------- */
-/* SPI CLK MODE */
-#define TEST_SPI_CLK_PHASE RTDM_SPI_CLKPHASE_LOW
-#define TEST_SPI_CLK_POLARITY RTDM_SPI_CLKPOLARITY_LOW
-/* Frequency : 5MHz */
-#define TEST_SPI_SPEED 20000000
-/* 16 bits per word */
-#define TEST_SPI_BITS_PER_WORD RTDM_SPI_8BPW
-/* Chip selects */
-#define TEST_SPI_CHIPSELECT1 RTDM_SPI_SS0
-#define TEST_SPI_CHIPSELECT2 RTDM_SPI_SS0
-/* Use the DMA from transfer > 4 bytes */
-#define TEST_SPI_DMA_BYTES_MIN 4
-
-#define NVRAM_SIZE 0x8000
-#define IDLEN 4
-#define CMDSIZE 3
-#define RETAIN_BUFFER_SIZE (NVRAM_SIZE - IDLEN)
-
-static RT_TASK RETAIN_task;
-static RT_MUTEX RETAIN_Mutex;
-static RT_EVENT RETAIN_Event;
-
-#pragma pack(push,1)
-/* Data protected by mutex */
-static struct priv_s {
- unsigned char cmd[CMDSIZE];
- struct buf_s {
- unsigned char id[IDLEN];
- unsigned char vars[RETAIN_BUFFER_SIZE];
- } buf;
-} priv;
-#pragma pack(pop)
-
-static unsigned short actual_size;
-static int retain_busy = 0;
-/* 0 : PLC can update. No SPI transmission undergoing
- 1 : PLC cannot update. SPI transmission undergoing */
-
-static int fd_spi;
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-static uint8_t rcmd[] = {
- /* Read, Addresssse */
- 0x03, 0x00, 0x00,
-};
-
-int SPI_Read(void *buf, unsigned int len){
- int status;
- int size;
- unsigned int uint;
- uint = 1;
- if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
- printf("Failed to lock CS\n");
- return 0;
- }
-
- status = write(fd_spi, rcmd, ARRAY_SIZE(rcmd));
- if (status < 0) {
- fprintf(stderr, "Failed to send read command. ERR : %d\n", status);
- return 0;
- }
-
- uint = 0;
- if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
- printf("Failed to unlock CS\n");
- return 0;
- }
-
- size = read(fd_spi, buf, len);
- if (size != len) {
- fprintf(stderr, "Failed to read %d bytes on the SPI bus. size : %d\n",
- len, size);
- return 0;
- }
-
- return size;
-}
-
-int SPI_Write(void *buf, unsigned int len){
- int status;
- status = write(fd_spi, buf, len);
- if (status < 0) {
- fprintf(stderr, "Failed to write memory. ERR : %d\n", status);
- return 0;
- }
- return len;
-}
-
-static void SPI_init(void)
-{
- unsigned long ulong;
- unsigned int uint;
-
- /* Open the SPI RTDM device */
- if ((fd_spi = open("/dev/rtdm/spi_apf28_rtdm", 0)) < 0) {
- printf("rt_spi_open error\n");
- return;
- }
-
- /* Bus configuration */
-
- /* Clock phase */
- uint = TEST_SPI_CLK_PHASE;
- if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_SET, &uint) < 0) {
- printf("Failed to configure the clock phase\n");
- return;
- }
- if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) {
- printf("Failed to get the clock phase\n");
- return;
- }
-
- /* Clock polarity */
- uint = TEST_SPI_CLK_POLARITY;
- if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_SET, &uint) < 0) {
- printf("Failed to configure the clock polarity\n");
- return;
- }
- if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) {
- printf("Failed to get the clock polarity\n");
- return;
- }
-
- /* Frequency */
- ulong = TEST_SPI_SPEED;
- if (ioctl(fd_spi, RTDM_SPI_FREQ_SET, &ulong) < 0) {
- printf("Failed to configure the frequency\n");
- return;
- }
- if (ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) {
- printf("Failed to get the frequency\n");
- return;
- }
-
- /* Bits per word */
- uint = TEST_SPI_BITS_PER_WORD;
- if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_SET, &uint) < 0) {
- printf("Failed to configure the BPW\n");
- return;
- }
- if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) {
- printf("Failed to get the BPW\n");
- return;
- }
-
- /* Chipselect */
- uint = TEST_SPI_CHIPSELECT1;
- if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_SET, &uint) < 0) {
- printf("Failed to configure the chip select\n");
- return;
- }
- if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) {
- printf("Failed to get the chip select\n");
- return;
- }
-
- /* DMA usage definition */
- uint = TEST_SPI_DMA_BYTES_MIN;
- if (ioctl(fd_spi, RTDM_SPI_DMA_SET, &uint) < 0) {
- printf("Failed to configure the DMA threshold\n");
- return;
- }
- if (ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) {
- printf("Failed to get the DMA threshold\n");
- return;
- }
-
- /* Prepare for future write commands */
- /* Write Command*/
- priv.cmd[0] = 0x02;
- /* Write Addresssse */
- priv.cmd[1] = 0x00;
- priv.cmd[2] = 0x00;
-}
-
-int NVRAM_Done = 0;
-
-void NVRAM_Init(void){
- int status;
- /* Set Sequencial access mode */
- uint8_t mbuf[] = {
- /* Mode, Sequ */
- 0x01, 0x40,
- };
-
- status = write(fd_spi, mbuf, ARRAY_SIZE(mbuf));
- if (status < 0) {
- printf("Failed to change mode. ERR : %d\n", status);
- return;
- }
- /* Read the whole NVRAM at start */
- SPI_Read(&priv.buf, NVRAM_SIZE);
- NVRAM_Done = 1;
-}
-
-void RETAIN_task_proc(void *arg)
-{
- unsigned int msk = 0;
- NVRAM_Init();
- while (!rt_event_wait(&RETAIN_Event, 1, &msk, EV_ANY, TM_INFINITE)) {
- if(rt_mutex_acquire(&RETAIN_Mutex, TM_INFINITE)) return;
- SPI_Write(&priv, CMDSIZE + actual_size + IDLEN);
- if(rt_event_clear(&RETAIN_Event, 1, NULL)) return;
- if(rt_mutex_release(&RETAIN_Mutex)) return;
- }
-}
-
-void InitRetain(void) /* TODO return error and care */
-{
- retain_busy = 0;
- if(rt_event_create (&RETAIN_Event, "RETAIN_Event", 0, 0))
- return;
- if(rt_mutex_create (&RETAIN_Mutex, "RETAIN_Mutex"))
- return;
- if(rt_task_create(&RETAIN_task, "RETAIN_task", 0, 50, T_JOINABLE))
- return;
-
- SPI_init(); /*TODO if error */
-
- NVRAM_Done = 0;
-
- if(rt_task_start(&RETAIN_task, &RETAIN_task_proc, NULL))
- return;
-
- int count = 1000000;
- while(!NVRAM_Done && count--){
- usleep(1);
- }
- if(!NVRAM_Done){
- /*error*/
- printf("NVRAM init timeout\n");
- }
-}
-
-void CleanupRetain(void)
-{
- rt_task_delete(&RETAIN_task);
- rt_task_join(&RETAIN_task);
- rt_mutex_delete(&RETAIN_Mutex);
- rt_event_delete(&RETAIN_Event);
-}
-
-void ValidateRetainBuffer(void)
-{
- if(retain_busy == 0){
- if(PLC_ID)
- memcpy(priv.buf.id, PLC_ID, IDLEN);
- retain_busy = 1;
- rt_mutex_release(&RETAIN_Mutex);
- rt_event_signal(&RETAIN_Event, 1);
- }
-}
-
-void InValidateRetainBuffer(void)
-{
- int ret = rt_mutex_acquire(&RETAIN_Mutex, TM_NONBLOCK);
- if(ret == -EWOULDBLOCK){
- /* mutex was unavailable */
- retain_busy = 1;
- }else if(ret == 0){
- /* mutex acquired */
- /* invalidate that buffer */
- bzero(&priv.buf.id[0], IDLEN);
- retain_busy = 0;
- actual_size = 0;
- }else{
- /* error */
- retain_busy = 1;
- }
-
- //printf("invalidate retain\n");
-}
-
-int CheckRetainBuffer(void)
-{
- /* compare RETAIN ID buffer with MD5 */
- /* return true if identical */
- if(PLC_ID){
- int res;
- res = memcmp(&priv.buf.id[0], PLC_ID, IDLEN) == 0;
- return res;
- }else{
- return 0;
- }
-}
-
-void Retain(unsigned int offset, unsigned int count, void *p)
-{
- if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE){
- /* write in RETAIN buffer at offset*/
- actual_size = offset + count;
- memcpy(&priv.buf.vars[offset], p, count);
- }
-}
-
-void Remind(unsigned int offset, unsigned int count, void *p)
-{
- if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE)
- /* read at offset in RETAIN buffer */
- memcpy(p, &priv.buf.vars[offset], count);
-}
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SOM28Target/XSD Tue Feb 19 11:35:41 2019 +0100
@@ -0,0 +1,9 @@
+<xsd:element name="%(target_name)s">
+ <xsd:complexType>
+ <xsd:attribute name="Compiler" type="xsd:string" use="optional" default="arm-unknown-linux-gnueabi-gcc"/>
+ <xsd:attribute name="CFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-linux-gnueabi-apf28 -DHAVE_RETAIN -pipe -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-variable -I../arm-linux-gnueabi-apf28/usr/include/xenomai/cobalt -I../arm-linux-gnueabi-apf28/usr/include/xenomai -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I../arm-linux-gnueabi-apf28/usr/include/xenomai/alchemy -D__COBALT_WRAP__ "/>
+ <xsd:attribute name="Linker" type="xsd:string" use="optional" default="arm-unknown-linux-gnueabi-gcc"/>
+ <xsd:attribute name="LDFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-linux-gnueabi-apf28 -lpthread -Wl,--no-as-needed -Wl,@../arm-linux-gnueabi-apf28/usr/lib/cobalt.wrappers -Wl,@../arm-linux-gnueabi-apf28/usr/lib/modechk.wrappers -lalchemy -lcopperplate -L../arm-linux-gnueabi-apf28/usr/lib -lcobalt -lmodechk -lpthread -lrt "/>
+ <xsd:attribute name="XenoConfig" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+</xsd:element>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SOM28Target/plc_SOM28_main_retain.c Tue Feb 19 11:35:41 2019 +0100
@@ -0,0 +1,314 @@
+
+#include <alchemy/event.h>
+#include <alchemy/mutex.h>
+#include <rtdm/rtdm.h>
+#include <rtdm/spi_apf28_rtdm_ioctl.h>
+#include <xenomai/init.h>
+
+
+/* SPI configurable parameters */
+/* --------------------------- */
+/* SPI CLK MODE */
+#define TEST_SPI_CLK_PHASE RTDM_SPI_CLKPHASE_LOW
+#define TEST_SPI_CLK_POLARITY RTDM_SPI_CLKPOLARITY_LOW
+/* Frequency : 5MHz */
+#define TEST_SPI_SPEED 20000000
+/* 16 bits per word */
+#define TEST_SPI_BITS_PER_WORD RTDM_SPI_8BPW
+/* Chip selects */
+#define TEST_SPI_CHIPSELECT1 RTDM_SPI_SS0
+#define TEST_SPI_CHIPSELECT2 RTDM_SPI_SS0
+/* Use the DMA from transfer > 4 bytes */
+#define TEST_SPI_DMA_BYTES_MIN 4
+
+#define NVRAM_SIZE 0x8000
+#define IDLEN 4
+#define CMDSIZE 3
+#define RETAIN_BUFFER_SIZE (NVRAM_SIZE - IDLEN)
+
+static RT_TASK RETAIN_task;
+static RT_MUTEX RETAIN_Mutex;
+static RT_EVENT RETAIN_Event;
+
+#pragma pack(push,1)
+/* Data protected by mutex */
+static struct priv_s {
+ unsigned char cmd[CMDSIZE];
+ struct buf_s {
+ unsigned char id[IDLEN];
+ unsigned char vars[RETAIN_BUFFER_SIZE];
+ } buf;
+} priv;
+#pragma pack(pop)
+
+static unsigned short actual_size;
+static int retain_busy = 0;
+/* 0 : PLC can update. No SPI transmission undergoing
+ 1 : PLC cannot update. SPI transmission undergoing */
+
+static int fd_spi;
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static uint8_t rcmd[] = {
+ /* Read, Addresssse */
+ 0x03, 0x00, 0x00,
+};
+
+int SPI_Read(void *buf, unsigned int len){
+ int status;
+ int size;
+ unsigned int uint;
+ uint = 1;
+ if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
+ printf("Failed to lock CS\n");
+ return 0;
+ }
+
+ status = write(fd_spi, rcmd, ARRAY_SIZE(rcmd));
+ if (status < 0) {
+ fprintf(stderr, "Failed to send read command. ERR : %d\n", status);
+ return 0;
+ }
+
+ uint = 0;
+ if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
+ printf("Failed to unlock CS\n");
+ return 0;
+ }
+
+ size = read(fd_spi, buf, len);
+ if (size != len) {
+ fprintf(stderr, "Failed to read %d bytes on the SPI bus. size : %d\n",
+ len, size);
+ return 0;
+ }
+
+ return size;
+}
+
+int SPI_Write(void *buf, unsigned int len){
+ int status;
+ status = write(fd_spi, buf, len);
+ if (status < 0) {
+ fprintf(stderr, "Failed to write memory. ERR : %d\n", status);
+ return 0;
+ }
+ return len;
+}
+
+static void SPI_init(void)
+{
+ unsigned long ulong;
+ unsigned int uint;
+
+ /* Open the SPI RTDM device */
+ if ((fd_spi = open("/dev/rtdm/spi_apf28_rtdm", 0)) < 0) {
+ printf("rt_spi_open error\n");
+ return;
+ }
+
+ /* Bus configuration */
+
+ /* Clock phase */
+ uint = TEST_SPI_CLK_PHASE;
+ if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_SET, &uint) < 0) {
+ printf("Failed to configure the clock phase\n");
+ return;
+ }
+ if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) {
+ printf("Failed to get the clock phase\n");
+ return;
+ }
+
+ /* Clock polarity */
+ uint = TEST_SPI_CLK_POLARITY;
+ if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_SET, &uint) < 0) {
+ printf("Failed to configure the clock polarity\n");
+ return;
+ }
+ if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) {
+ printf("Failed to get the clock polarity\n");
+ return;
+ }
+
+ /* Frequency */
+ ulong = TEST_SPI_SPEED;
+ if (ioctl(fd_spi, RTDM_SPI_FREQ_SET, &ulong) < 0) {
+ printf("Failed to configure the frequency\n");
+ return;
+ }
+ if (ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) {
+ printf("Failed to get the frequency\n");
+ return;
+ }
+
+ /* Bits per word */
+ uint = TEST_SPI_BITS_PER_WORD;
+ if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_SET, &uint) < 0) {
+ printf("Failed to configure the BPW\n");
+ return;
+ }
+ if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) {
+ printf("Failed to get the BPW\n");
+ return;
+ }
+
+ /* Chipselect */
+ uint = TEST_SPI_CHIPSELECT1;
+ if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_SET, &uint) < 0) {
+ printf("Failed to configure the chip select\n");
+ return;
+ }
+ if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) {
+ printf("Failed to get the chip select\n");
+ return;
+ }
+
+ /* DMA usage definition */
+ uint = TEST_SPI_DMA_BYTES_MIN;
+ if (ioctl(fd_spi, RTDM_SPI_DMA_SET, &uint) < 0) {
+ printf("Failed to configure the DMA threshold\n");
+ return;
+ }
+ if (ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) {
+ printf("Failed to get the DMA threshold\n");
+ return;
+ }
+
+ /* Prepare for future write commands */
+ /* Write Command*/
+ priv.cmd[0] = 0x02;
+ /* Write Addresssse */
+ priv.cmd[1] = 0x00;
+ priv.cmd[2] = 0x00;
+}
+
+int NVRAM_Done = 0;
+
+void NVRAM_Init(void){
+ int status;
+ /* Set Sequencial access mode */
+ uint8_t mbuf[] = {
+ /* Mode, Sequ */
+ 0x01, 0x40,
+ };
+
+ status = write(fd_spi, mbuf, ARRAY_SIZE(mbuf));
+ if (status < 0) {
+ printf("Failed to change mode. ERR : %d\n", status);
+ return;
+ }
+ /* Read the whole NVRAM at start */
+ SPI_Read(&priv.buf, NVRAM_SIZE);
+ NVRAM_Done = 1;
+}
+
+void RETAIN_task_proc(void *arg)
+{
+ unsigned int msk = 0;
+ NVRAM_Init();
+ while (!rt_event_wait(&RETAIN_Event, 1, &msk, EV_ANY, TM_INFINITE)) {
+ if(rt_mutex_acquire(&RETAIN_Mutex, TM_INFINITE)) return;
+ SPI_Write(&priv, CMDSIZE + actual_size + IDLEN);
+ if(rt_event_clear(&RETAIN_Event, 1, NULL)) return;
+ if(rt_mutex_release(&RETAIN_Mutex)) return;
+ }
+}
+
+void InitRetain(void) /* TODO return error and care */
+{
+ retain_busy = 0;
+ if(rt_event_create (&RETAIN_Event, "RETAIN_Event", 0, 0))
+ return;
+ if(rt_mutex_create (&RETAIN_Mutex, "RETAIN_Mutex"))
+ return;
+ if(rt_task_create(&RETAIN_task, "RETAIN_task", 0, 50, T_JOINABLE))
+ return;
+
+ SPI_init(); /*TODO if error */
+
+ NVRAM_Done = 0;
+
+ if(rt_task_start(&RETAIN_task, &RETAIN_task_proc, NULL))
+ return;
+
+ int count = 1000000;
+ while(!NVRAM_Done && count--){
+ usleep(1);
+ }
+ if(!NVRAM_Done){
+ /*error*/
+ printf("NVRAM init timeout\n");
+ }
+}
+
+void CleanupRetain(void)
+{
+ rt_task_delete(&RETAIN_task);
+ rt_task_join(&RETAIN_task);
+ rt_mutex_delete(&RETAIN_Mutex);
+ rt_event_delete(&RETAIN_Event);
+}
+
+void ValidateRetainBuffer(void)
+{
+ if(retain_busy == 0){
+ if(PLC_ID)
+ memcpy(priv.buf.id, PLC_ID, IDLEN);
+ retain_busy = 1;
+ rt_mutex_release(&RETAIN_Mutex);
+ rt_event_signal(&RETAIN_Event, 1);
+ }
+}
+
+void InValidateRetainBuffer(void)
+{
+ int ret = rt_mutex_acquire(&RETAIN_Mutex, TM_NONBLOCK);
+ if(ret == -EWOULDBLOCK){
+ /* mutex was unavailable */
+ retain_busy = 1;
+ }else if(ret == 0){
+ /* mutex acquired */
+ /* invalidate that buffer */
+ bzero(&priv.buf.id[0], IDLEN);
+ retain_busy = 0;
+ actual_size = 0;
+ }else{
+ /* error */
+ retain_busy = 1;
+ }
+
+ //printf("invalidate retain\n");
+}
+
+int CheckRetainBuffer(void)
+{
+ /* compare RETAIN ID buffer with MD5 */
+ /* return true if identical */
+ if(PLC_ID){
+ int res;
+ res = memcmp(&priv.buf.id[0], PLC_ID, IDLEN) == 0;
+ return res;
+ }else{
+ return 0;
+ }
+}
+
+void Retain(unsigned int offset, unsigned int count, void *p)
+{
+ if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE){
+ /* write in RETAIN buffer at offset*/
+ actual_size = offset + count;
+ memcpy(&priv.buf.vars[offset], p, count);
+ }
+}
+
+void Remind(unsigned int offset, unsigned int count, void *p)
+{
+ if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE)
+ /* read at offset in RETAIN buffer */
+ memcpy(p, &priv.buf.vars[offset], count);
+}
+
+