--- a/LPCManager.py Fri Mar 13 20:35:22 2015 +0100
+++ b/LPCManager.py Sat Mar 14 18:32:06 2015 +0100
@@ -90,7 +90,7 @@
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.c_retain":os.path.join(_lpcmanager_path,
+ "plc_MC9_main_retain.c":os.path.join(_lpcmanager_path, "MC9target", "plc_MC9_main_retain.c")}}
from ProjectController import ProjectController
--- a/MC9target/plc_MC9_main_retain.c Fri Mar 13 20:35:22 2015 +0100
+++ b/MC9target/plc_MC9_main_retain.c Sat Mar 14 18:32:06 2015 +0100
@@ -1,20 +1,314 @@
-int CheckRetainBuffer(void)
+#include <native/event.h> +#include <native/mutex.h> +#include <rtdm/spi_apf28_rtdm_ioctl.h> +#define TEST_SPI_BUS_NUMBER 2 +/* SPI configurable parameters */ +/* --------------------------- */ +#define TEST_SPI_CLK_PHASE RTDM_SPI_CLKPHASE_LOW +#define TEST_SPI_CLK_POLARITY RTDM_SPI_CLKPOLARITY_LOW +#define TEST_SPI_SPEED 20000000 +#define TEST_SPI_BITS_PER_WORD RTDM_SPI_8BPW +#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 RETAIN_BUFFER_SIZE (NVRAM_SIZE - IDLEN) +static RT_TASK RETAIN_task; +static RT_MUTEX RETAIN_Mutex; +static RT_EVENT RETAIN_Event; +/* Data protected by mutex */ + unsigned char cmd[CMDSIZE]; + unsigned char id[IDLEN]; + unsigned char vars[RETAIN_BUFFER_SIZE]; +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 */ +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +static uint8_t rcmd[] = { +int SPI_Read(void *buf, unsigned int len){ + if (rt_dev_ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) { + printf("Failed to lock CS\n"); + status = rt_dev_write(fd_spi, rcmd, ARRAY_SIZE(rcmd)); + fprintf(stderr, "Failed to send read command. ERR : %d\n", status); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) { + printf("Failed to unlock CS\n"); + size = rt_dev_read(fd_spi, buf, len); + fprintf(stderr, "Failed to read %d bytes on the SPI bus. size : %d\n", +int SPI_Write(void *buf, unsigned int len){ + status = rt_dev_write(fd_spi, buf, len); + fprintf(stderr, "Failed to write memory. ERR : %d\n", status); +static void SPI_init(void)
+ /* Open the SPI RTDM device */ + if ((fd_spi = rt_dev_open("spi_apf28_rtdm", TEST_SPI_BUS_NUMBER)) < 0) { + printf("rt_spi_open error\n"); + /* Bus configuration */ + printf("Configure the bus :\n"); + uint = TEST_SPI_CLK_PHASE; + printf("> (SET) Clock phase : %d \n", uint); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPHASE_SET, &uint) < 0) { + printf("Failed to configure the clock phase\n"); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) { + printf("Failed to get the clock phase\n"); + printf("> (GET) Clock phase : %d \n", uint); + uint = TEST_SPI_CLK_POLARITY; + printf("> (SET) Clock polarity : %d \n", uint); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_SET, &uint) < 0) { + printf("Failed to configure the clock polarity\n"); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) { + printf("Failed to get the clock polarity\n"); + printf("> (GET) Clock polarity : %d \n", uint); + ulong = TEST_SPI_SPEED; + printf("> (SET) Frequency : %d \n", ulong); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_FREQ_SET, &ulong) < 0) { + printf("Failed to configure the frequency\n"); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) { + printf("Failed to get the frequency\n"); + printf("> (GET) Frequency : %lu \n", ulong); + uint = TEST_SPI_BITS_PER_WORD; + printf("> (SET) Bits per word : %d \n", uint); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_BITSPERWORD_SET, &uint) < 0) { + printf("Failed to configure the BPW\n"); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) { + printf("Failed to get the BPW\n"); + printf("> (GET) Bits per word : %d \n", uint); + uint = TEST_SPI_CHIPSELECT1; + printf("> (SET) Chip select : %d \n", uint); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_CHIPSELECT_SET, &uint) < 0) { + printf("Failed to configure the chip select\n"); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) { + printf("Failed to get the chip select\n"); + printf("> (GET) Chip select : %d \n", uint); + /* DMA usage definition */ + uint = TEST_SPI_DMA_BYTES_MIN; + printf("> (SET) Use the DMA from %d bytes\n", uint); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_DMA_SET, &uint) < 0) { + printf("Failed to configure the DMA threshold\n"); + if (rt_dev_ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) { + printf("Failed to get the DMA threshold\n"); + printf("> (GET) DMA threshold : %d bytes \n", uint); + /* Set Sequencial access mode */ + status = rt_dev_write(fd_spi, mbuf, ARRAY_SIZE(mbuf)); + printf("Failed to change mode. ERR : %d\n", status); + /* Read the whole NVRAM at start */ + SPI_Read(&priv.buf, NVRAM_SIZE); + /* Prepare for future write commands */ +void RETAIN_task_proc(void *arg) + 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; + if(rt_event_create (&RETAIN_Event, "RETAIN_Event", 0, 0)) + if(rt_mutex_create (&RETAIN_Mutex, "RETAIN_Mutex")) + if(rt_task_create(&RETAIN_task, "RETAIN_task", 0, 50, T_JOINABLE)) + SPI_init(); /*TODO if error */ + if(rt_task_start(&RETAIN_task, &RETAIN_task_proc, NULL)) +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)
+ memcpy(priv.buf.id, PLCID, IDLEN); + 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 */ + /* invalidate that buffer */ + bzero(&priv.buf.id[0], IDLEN); + //printf("invalidate retain\n"); +int CheckRetainBuffer(void) + /* compare RETAIN ID buffer with MD5 */ + /* return true if identical */ + res = memcmp(&priv.buf.id[0], PLCID, IDLEN) == 0; void Retain(unsigned int offset, unsigned int count, void *p)
+ rt_printf("retain %d %d\n", offset, count); + 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)
+ rt_printf("remind %d %d\n", offset, count); + if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE) + /* read at offset in RETAIN buffer */ + memcpy(p, &priv.buf.vars[offset], count);