etisserant@0: /* etisserant@0: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@0: etisserant@0: Author: Christian Fortin (canfestival@canopencanada.ca) etisserant@0: etisserant@0: See COPYING file for copyrights details. etisserant@0: etisserant@0: This library is free software; you can redistribute it and/or etisserant@0: modify it under the terms of the GNU Lesser General Public etisserant@0: License as published by the Free Software Foundation; either etisserant@0: version 2.1 of the License, or (at your option) any later version. etisserant@0: etisserant@0: This library is distributed in the hope that it will be useful, etisserant@0: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@0: Lesser General Public License for more details. etisserant@0: etisserant@0: You should have received a copy of the GNU Lesser General Public etisserant@0: License along with this library; if not, write to the Free Software etisserant@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@0: */ etisserant@0: etisserant@0: #include <stdlib.h> etisserant@0: etisserant@0: #include <sys/time.h> etisserant@0: #include <signal.h> etisserant@0: etisserant@0: #include <cyg/kernel/kapi.h> etisserant@0: #include <cyg/hal/hal_arch.h> etisserant@0: etisserant@0: #include "applicfg.h" etisserant@0: #include <data.h> etisserant@0: #include <def.h> etisserant@0: #include <can.h> etisserant@0: #include <can_driver.h> etisserant@0: #include <objdictdef.h> etisserant@0: #include <objacces.h> etisserant@0: etisserant@0: #include "lpc2138_pinout.h" etisserant@0: #include "lpc2138_defs.h" etisserant@0: #include "lpc2138.h" etisserant@0: etisserant@0: #include "sja1000.h" etisserant@0: etisserant@0: #include "time_slicer.h" etisserant@0: etisserant@0: etisserant@0: /* etisserant@0: SEND/RECEIVE etisserant@0: */ etisserant@0: CAN_HANDLE canOpen(s_BOARD *board) etisserant@0: { etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: int canClose(CAN_HANDLE fd0) etisserant@0: { etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: UNS8 canReceive(CAN_HANDLE fd0, Message *m) etisserant@0: /* etisserant@0: Message *m : etisserant@0: typedef struct { etisserant@0: SHORT_CAN cob_id; // l'ID du mesg etisserant@0: UNS8 rtr; // remote transmission request. 0 if not rtr, etisserant@0: // 1 for a rtr message etisserant@0: UNS8 len; // message length (0 to 8) etisserant@0: UNS8 data[8]; // data etisserant@0: } Message; etisserant@0: etisserant@0: Fill the structure "Message" with data from the CAN receive buffer etisserant@0: etisserant@0: return : 0 etisserant@0: */ etisserant@0: { etisserant@0: /* etisserant@0: the sja1000 must be set to the PeliCAN mode etisserant@0: */ etisserant@0: m->cob_id.w = sja1000_read(16) + (sja1000_read(17)<<8); // IO_PORTS_16(CAN0 + CANRCVID) >> 5 etisserant@0: etisserant@0: m->rtr = (sja1000_read(17) >> 4) & 0x01; // (IO_PORTS_8(CAN0 + CANRCVID + 1) >> 4) & 0x01; etisserant@0: etisserant@0: m->len = sja1000_read(18); etisserant@0: etisserant@0: m->data[0] = sja1000_read(19); etisserant@0: m->data[1] = sja1000_read(20); etisserant@0: m->data[2] = sja1000_read(21); etisserant@0: m->data[3] = sja1000_read(22); etisserant@0: m->data[4] = sja1000_read(23); etisserant@0: m->data[5] = sja1000_read(24); etisserant@0: m->data[6] = sja1000_read(25); etisserant@0: m->data[7] = sja1000_read(26); etisserant@0: etisserant@0: sja1000_write(CMR, 1<<RRB ); // release fifo etisserant@0: etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: UNS8 canSend(CAN_HANDLE fd0, Message *m) etisserant@0: /* etisserant@0: Message *m : etisserant@0: typedef struct { etisserant@0: SHORT_CAN cob_id; // l'ID du mesg etisserant@0: UNS8 rtr; // remote transmission request. 0 if not rtr, etisserant@0: // 1 for a rtr message etisserant@0: UNS8 len; // message length (0 to 8) etisserant@0: UNS8 data[8]; // data etisserant@0: } Message; etisserant@0: etisserant@0: Send the content of the structure "Message" to the CAN transmit buffer etisserant@0: etisserant@0: return : 0 if OK, 1 if error etisserant@0: */ etisserant@0: { etisserant@0: unsigned char rec_buf; etisserant@0: etisserant@0: do etisserant@0: { etisserant@0: rec_buf = sja1000_read(SR); etisserant@0: } etisserant@0: while ( (rec_buf & (1<<TBS))==0); // loop until TBS high etisserant@0: etisserant@0: sja1000_write(16, m->cob_id.w & 0xff); etisserant@0: sja1000_write(17, (m->cob_id.w >> 8) & 0xff); etisserant@0: sja1000_write(18, m->len); etisserant@0: etisserant@0: sja1000_write(19, m->data[0]); // tx data 1 etisserant@0: sja1000_write(20, m->data[1]); // tx data 2 etisserant@0: sja1000_write(21, m->data[2]); // tx data 3 etisserant@0: sja1000_write(22, m->data[3]); // tx data 4 etisserant@0: sja1000_write(23, m->data[4]); // tx data 5 etisserant@0: sja1000_write(24, m->data[5]); // tx data 6 etisserant@0: sja1000_write(25, m->data[6]); // tx data 7 etisserant@0: sja1000_write(26, m->data[7]); // tx data 8 etisserant@0: etisserant@0: sja1000_write(CMR,( (0<<SRR) | (0<<CDO) | (0<<RRB) | (0<<AT) | (1<<TR))); etisserant@0: do etisserant@0: { etisserant@0: rec_buf = sja1000_read(SR); etisserant@0: } etisserant@0: while ( (rec_buf & (1<<TBS))==0); // loop until TBS high etisserant@0: etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /* etisserant@0: SEQUENTIAL I/O TO FLASH etisserant@0: those functions are for continous writing and read etisserant@0: */ etisserant@0: etisserant@0: etisserant@0: int nvram_open(void) etisserant@0: { oremeq@3: int n = NVRAM_BLOCK_SIZE / sizeof(unsigned int); oremeq@3: etisserant@0: /* some actions to initialise the flash */ etisserant@0: data_len = 0; oremeq@3: data_num_pages = 0; oremeq@3: oremeq@3: data_page = (unsigned int *)malloc(sizeof(unsigned int) * n); oremeq@3: memset(data_page, 0, sizeof(unsigned int)*n); etisserant@0: etisserant@0: if (data_page == NULL) etisserant@0: return -1; etisserant@0: oremeq@3: regs_page = (unsigned int *)malloc(sizeof(unsigned int) * n); oremeq@3: memset(regs_page, 0, sizeof(unsigned int)*n); oremeq@3: if (regs_page == NULL) oremeq@3: return -2; oremeq@3: oremeq@3: iat_flash_read_regs(); oremeq@3: oremeq@3: /* start the data at the location specified in the registers */ oremeq@3: if (0) /* for now it is 0, but put here a test to know whether oremeq@3: or not the NVRAM has been written before */ oremeq@3: data_addr = regs_page[1]; oremeq@3: else oremeq@3: data_addr = NVRAM_BLOCK_SIZE; /* let start at block 1 */ oremeq@3: etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: void nvram_close(void) etisserant@0: { oremeq@3: /* write the last page before closing */ oremeq@3: iat_flash_write_page(data_addr); oremeq@3: etisserant@0: /* some actions to end accessing the flash */ etisserant@0: free(data_page); oremeq@3: oremeq@3: regs_page[4] = data_num_pages; oremeq@3: /* write the registers to the NVRAM before closing */ oremeq@3: iat_flash_write_regs(); oremeq@3: free(regs_page); oremeq@3: } oremeq@3: oremeq@3: oremeq@3: void nvram_set_pos(UNS32 pos) oremeq@3: /* set the current position in the NVRAM to pos */ oremeq@3: { oremeq@3: } oremeq@3: oremeq@3: oremeq@3: void nvram_new_firmwave() oremeq@3: { oremeq@3: /* oremeq@3: this function is called whenever a new firmware is about oremeq@3: to be written in the NVRAM oremeq@3: */ oremeq@3: data_addr = regs_page[1] + regs_page[4]*NVRAM_BLOCK_SIZE; oremeq@3: if (data_addr > NVRAM_MAX_SIZE) oremeq@3: data_addr = NVRAM_BLOCK_SIZE; etisserant@0: } etisserant@0: etisserant@0: int _get_data_len(int type) etisserant@0: { etisserant@0: int len = 0; /* number of bytes */ etisserant@0: switch(type) etisserant@0: { etisserant@0: case boolean: etisserant@0: len = 1; etisserant@0: break; etisserant@0: etisserant@0: case int8: etisserant@0: case uint8: etisserant@0: len = 1; etisserant@0: break; etisserant@0: case int16: etisserant@0: case uint16: etisserant@0: len = 2; etisserant@0: break; etisserant@0: case int24: etisserant@0: case uint24: etisserant@0: len = 3; etisserant@0: break; etisserant@0: case int32: etisserant@0: case uint32: etisserant@0: case real32: etisserant@0: len = 4; etisserant@0: break; etisserant@0: case int40: etisserant@0: case uint40: etisserant@0: len = 5; etisserant@0: break; etisserant@0: case int48: etisserant@0: case uint48: etisserant@0: len = 6; etisserant@0: break; etisserant@0: case int56: etisserant@0: case uint56: etisserant@0: len = 7; etisserant@0: break; etisserant@0: case int64: etisserant@0: case uint64: etisserant@0: case real64: etisserant@0: len = 8; etisserant@0: break; etisserant@0: #if 0 etisserant@0: /* TO DO */ etisserant@0: case visible_string: etisserant@0: case octet_string: etisserant@0: case unicode_string: etisserant@0: case time_of_day: etisserant@0: case time_difference: etisserant@0: #endif etisserant@0: } etisserant@0: etisserant@0: return len; etisserant@0: } etisserant@0: etisserant@0: oremeq@3: char nvram_write_data(int type, int access_attr, void *data) etisserant@0: /* return 0 if successfull */ etisserant@0: { etisserant@0: int len = _get_data_len(type); etisserant@0: oremeq@3: if (data_len+len > NVRAM_BLOCK_SIZE) etisserant@0: { etisserant@0: iat_flash_write_page(data_addr); etisserant@0: data_len = 0; oremeq@3: data_addr += NVRAM_BLOCK_SIZE; oremeq@3: oremeq@3: /* wrap-around address pointer */ oremeq@3: if (data_addr > NVRAM_MAX_SIZE) oremeq@3: data_addr = NVRAM_BLOCK_SIZE; oremeq@3: oremeq@3: data_num_pages++; etisserant@0: } etisserant@0: etisserant@0: memcpy(((char *)data_page)+data_len, data, len); etisserant@0: etisserant@0: data_len += len; etisserant@0: etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: oremeq@3: char nvram_read_data(int type, int access_attr, void *data) etisserant@0: /* return 0 if successful */ etisserant@0: { etisserant@0: int len = _get_data_len(type); etisserant@0: oremeq@3: if (data_len+len > NVRAM_BLOCK_SIZE) etisserant@0: { oremeq@3: data_addr += NVRAM_BLOCK_SIZE; oremeq@3: oremeq@3: /* wrap-around address pointer */ oremeq@3: if (data_addr > NVRAM_MAX_SIZE) oremeq@3: data_addr = NVRAM_BLOCK_SIZE; oremeq@3: etisserant@0: iat_flash_read_page(data_addr); etisserant@0: data_len = 0; etisserant@0: } etisserant@0: etisserant@0: memcpy(data, ((char *)data_page)+data_len, len); etisserant@0: etisserant@0: data_len += len; etisserant@0: etisserant@0: return 0; etisserant@0: } etisserant@0: oremeq@3: /* oremeq@3: NVRAM registers at block 0 oremeq@3: pos description oremeq@3: 0 version of the current dictionnary oremeq@3: 1 starting address for data block oremeq@3: 2 date of last writing oremeq@3: 3 address of the previous dictionnary oremeq@3: 4 size in pages of the current dict oremeq@3: */ oremeq@3: void nvram_write_reg(UNS32 reg, UNS16 pos) oremeq@3: /* write reg at the position in the data block 0 */ oremeq@3: { oremeq@3: regs_page[pos] = reg; oremeq@3: } oremeq@3: oremeq@3: UNS32 nvram_read_reg(UNS16 pos) oremeq@3: /* read reg at the position in the data block 0 */ oremeq@3: { oremeq@3: return regs_page[pos]; oremeq@3: } oremeq@3: etisserant@0: etisserant@0: /* etisserant@0: LED etisserant@0: */ etisserant@0: oremeq@3: void led_set_redgreen(UNS8 bits) oremeq@3: /* bits : each bit of this uns8 is assigned a led oremeq@3: 0=off, 1=on oremeq@3: */ etisserant@0: { etisserant@0: lpc2138_redgreenled_set(bits); etisserant@0: } etisserant@0: