lpcmanager

Retain buffer implemntation for spi/rtdm

2015-03-14, Edouard Tisserant
8914a16a2c60
Parents df0a8ac7aeab
Children 8bb24e830620
Retain buffer implemntation for spi/rtdm
--- 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 Beremiz import *
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/rtdm.h>
+#include <rtdm/spi_apf28_rtdm_ioctl.h>
+
+#define TEST_SPI_BUS_NUMBER 2
+
+/* 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 (rt_dev_ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
+ printf("Failed to lock CS\n");
+ return 0;
+ }
+
+ status = rt_dev_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 (rt_dev_ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
+ printf("Failed to unlock CS\n");
+ return 0;
+ }
+
+ size = rt_dev_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 = rt_dev_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)
{
- return 1;
+ int status;
+ unsigned long ulong;
+ unsigned int uint;
+
+ /* 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");
+ return;
+ }
+
+ /* Bus configuration */
+ printf("Configure the bus :\n");
+
+ /* Clock phase */
+ 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");
+ return;
+ }
+ if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) {
+ printf("Failed to get the clock phase\n");
+ return;
+ }
+ printf("> (GET) Clock phase : %d \n", uint);
+
+ /* Clock polarity */
+ 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");
+ return;
+ }
+ if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) {
+ printf("Failed to get the clock polarity\n");
+ return;
+ }
+ printf("> (GET) Clock polarity : %d \n", uint);
+
+ /* Frequency */
+ 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");
+ return;
+ }
+ if (rt_dev_ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) {
+ printf("Failed to get the frequency\n");
+ return;
+ }
+ printf("> (GET) Frequency : %lu \n", ulong);
+
+ /* Bits per word */
+ 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");
+ return;
+ }
+ if (rt_dev_ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) {
+ printf("Failed to get the BPW\n");
+ return;
+ }
+ printf("> (GET) Bits per word : %d \n", uint);
+
+ /* Chipselect */
+ 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");
+ return;
+ }
+ if (rt_dev_ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) {
+ printf("Failed to get the chip select\n");
+ return;
+ }
+ 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");
+ return;
+ }
+ if (rt_dev_ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) {
+ printf("Failed to get the DMA threshold\n");
+ return;
+ }
+ printf("> (GET) DMA threshold : %d bytes \n", uint);
+
+ /* Set Sequencial access mode */
+ uint8_t mbuf[] = {
+ /* Mode, Sequ */
+ 0x01, 0x40,
+ };
+
+ status = rt_dev_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);
+
+ /* Prepare for future write commands */
+ /* Write Command*/
+ priv.cmd[0] = 0x02;
+ /* Write Addresssse */
+ priv.cmd[1] = 0x00;
+ priv.cmd[2] = 0x00;
+}
+
+void RETAIN_task_proc(void *arg)
+{
+ unsigned long msk = 0;
+ 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)
+{
+ rt_print_auto_init(1);
+ 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 */
+
+ if(rt_task_start(&RETAIN_task, &RETAIN_task_proc, NULL))
+ return;
+}
+
+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(PLCID)
+ memcpy(priv.buf.id, PLCID, 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(PLCID){
+ int res;
+ res = memcmp(&priv.buf.id[0], PLCID, IDLEN) == 0;
+ return res;
+ }else{
+ return 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);
}
+
+