lpcmanager

Default UART buffer is now short and baudrate is 19200. Modules that use short uart buffer should not have buffer size and baudrate redefined in xml module description file. This is necessary for compatibility with MC8.
#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)
{
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 */
/* Clock phase */
uint = TEST_SPI_CLK_PHASE;
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;
}
/* Clock polarity */
uint = TEST_SPI_CLK_POLARITY;
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;
}
/* Frequency */
ulong = TEST_SPI_SPEED;
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;
}
/* Bits per word */
uint = TEST_SPI_BITS_PER_WORD;
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;
}
/* Chipselect */
uint = TEST_SPI_CHIPSELECT1;
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;
}
/* DMA usage definition */
uint = TEST_SPI_DMA_BYTES_MIN;
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;
}
/* 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 = 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);
NVRAM_Done = 1;
}
void RETAIN_task_proc(void *arg)
{
unsigned long 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(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)
{
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);
}