]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/can_lpcbusemu.c
Merge master into can-usb1 branch to include proc update for 3.12+ kernels.
[lincan.git] / embedded / app / usbcan / can_lpcbusemu.c
1 /**
2 can.c
3
4 Routines for sending and receiving messages for configuration and/or
5 communication over CAN network using a SJA1000 transceiver.
6 For use in UL_USB1 module, it runs in Intel mode.
7 See documentation for details.
8
9 */
10
11
12 #include "can/can.h"
13
14
15 /***********************************************************************
16  * Microsecond delay routine
17  ***********************************************************************/
18 void udelay(long time)
19 {
20   volatile long ticks=(time * CCLK) / 2000000;
21   do{
22     ticks--;
23   } while(ticks>0);
24 }
25
26
27 inline void can_data_pins_dir_output(void)
28 {
29         IO1DIR|=P1_SJA1000_DATA_PINS; // Port as output to send data
30 }
31
32 inline void can_data_pins_dir_input(void)
33 {
34         IO1DIR&=~P1_SJA1000_DATA_PINS; // Sets port as input
35 }
36
37 inline void can_data_pins_set_value(uint8_t data)
38 {
39         uint32_t val = __val2mfld(P1_SJA1000_DATA_PINS,data);
40         /*
41          * Clear only that pins, which need that, lower transition
42          * frequency and eliminate spikes
43          */
44         IO1CLR= val ^ P1_SJA1000_DATA_PINS;
45         IO1SET= val;
46 }
47
48 inline uint8_t can_data_pins_get_value(void)
49 {
50         return __mfld2val(P1_SJA1000_DATA_PINS,IO1PIN);
51 }
52
53
54 void can_comm_init()
55 {
56         //CANMSG("Start can_comm_init\n");
57         IO1DIR |= P1_OUT_PORT_CS_PIN|P1_SJA1000_RST_PIN;
58         // Due to change in design there is CS_PIN connected with ALE_PIN and ALE_PIN connection to LPC is interrupted
59         // We don't use ALE_PIN
60         //IO0DIR|=P0_SJA1000_ALE_PIN|P0_SJA1000_CS_PIN|P0_SJA1000_RD_PIN|P0_SJA1000_WR_PIN;
61         IO0DIR|=P0_SJA1000_CS_PIN|P0_SJA1000_RD_PIN|P0_SJA1000_WR_PIN;
62         IO0DIR&=~(P0_SJA1000_INT_PIN);
63
64         SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
65         CLR_OUT_PIN(IO1,P1_SJA1000_RST_PIN);
66         SJA1000_INIT_DELAY();
67         SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
68         // Due to change in design there is CS_PIN connected with ALE_PIN and ALE_PIN connection to LPC is interrupted
69         //      CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
70         SET_OUT_PIN(IO1,P1_SJA1000_RST_PIN);
71         SJA1000_INIT_DELAY();
72 }
73
74 void can_write(uint8_t data, uint8_t address)
75 {
76         can_data_pins_dir_output();
77         // Set memory address
78         can_data_pins_set_value(address);
79         // Init
80         SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN);     // Stays high on write
81         SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Stays high on address write
82         SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN); // Sets output buffers to third state
83         //SJA1000_DELAY();
84         //SET_OUT_PIN(IO0,P0_SJA1000_ALE_PIN); // Start command
85
86         //SJA1000_DELAY();
87         //CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN); // Makes address active
88         CLR_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
89         //SJA1000_DELAY();
90
91         // Setting data
92         can_data_pins_set_value(data);
93
94         CLR_OUT_PIN(IO0,P0_SJA1000_WR_PIN);
95         CLR_OUT_PIN(IO0,P0_SJA1000_WR_PIN);
96         //SJA1000_DELAY();
97         SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Data should be accepted by now
98         SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
99         //SJA1000_DELAY();
100 }
101
102 uint8_t can_read(const uint8_t address)
103 {
104         uint8_t data;
105
106         can_data_pins_dir_output();
107         // Set memory address
108         can_data_pins_set_value(address);
109         // Init
110         SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Stays high on read
111         SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN); // Stays high while entering address
112         SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
113         //SJA1000_DELAY();
114         //SET_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
115
116         //SJA1000_DELAY();
117         //CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
118         CLR_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
119
120         // Get data
121
122         can_data_pins_dir_input();
123         CLR_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
124         CLR_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
125         //SJA1000_DELAY();
126         data = can_data_pins_get_value();
127         SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
128         SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
129         //SJA1000_DELAY();
130
131         return data;
132 }
133
134 int can_init(){
135         uint8_t data=0,count=0;
136         do {
137                 can_comm_init();
138                 data = can_read(SJAMOD);
139                 if (count++ > 50)
140                         return -1;
141         } while (!(data&sjaMOD_RM));
142
143         data=sjaCDR_CLKOUT_DIV1|sjaCDR_CLK_OFF|sjaCDR_CBP|sjaCDR_PELICAN;
144         can_write(data, SJACDR);
145
146         // Single acceptance filter, reset mode
147         data=sjaMOD_AFM|sjaMOD_RM;
148         can_write(data, SJAMOD);
149
150         // Enabling all interrupt sources
151         data=sjaENABLE_INTERRUPTS;
152         can_write(data, SJAIER);
153
154         // Accept all messages
155         data=0xFF;
156         can_write(data, SJAAMR0);
157         can_write(data, SJAAMR0+1);
158         can_write(data, SJAAMR0+2);
159         can_write(data, SJAAMR0+3);
160
161         data=sjaCMR_CDO;
162         can_write(data, SJACMR);
163
164         return 0;
165 }