lpcmanager

9cb1cbceeadc
Prevent dblquotes and carriage return to end in variables options
#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;
*/
return -EIO;
}
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;
*/
return -EIO;
}
static void SPI_init(void)
{
#if 0
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;
#endif
}
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));
status = -EIO;
if (status < 0) {
printf("RETAIN : Failed to change mode. ERR : %d\n", status);
// TODO: remove this !!!
NVRAM_Done = 1;
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){
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);
}