]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/lpc17xx_can.c
first version, only transmitting CAN messages without usage of queue system from...
[lincan.git] / embedded / app / usbcan / lpc17xx_can.c
1 #include "can/lpc17xx_can.h"
2
3 static void CAN_configPin();
4 static void CAN_setBusTiming(uint32_t baudrate);
5
6 //------------------------------------------
7
8 static void CAN_configPin(){
9
10 //      CAN1 - select P0.0 as RD1. P0.1 as TD1
11
12         uint32_t pinsel0;
13         uint32_t pinmode0;
14         uint32_t pinmode_od0;
15         uint8_t pinsel0_val = 1;
16         uint8_t pinmode0_val = 0;
17         uint8_t pinmode_od0_val = 0;
18
19
20         pinsel0 = PINSEL0;
21         pinsel0 &= ~CAN1_RX_MASK;
22         pinsel0 &= ~CAN1_TX_MASK;
23         pinsel0 |= __val2mfld(CAN1_RX_MASK, pinsel0_val);
24         pinsel0 |= __val2mfld(CAN1_TX_MASK, pinsel0_val);
25         PINSEL0 = pinsel0;
26
27         pinmode0 = PINMODE0;
28         pinmode0 &= ~CAN1_RX_MASK;
29         pinmode0 &= ~CAN1_TX_MASK;
30         pinmode0 |= __val2mfld(CAN1_RX_MASK, pinmode0_val);
31         pinmode0 |= __val2mfld(CAN1_TX_MASK, pinmode0_val);
32         PINMODE0 = pinmode0;
33
34         pinmode_od0 = PINMODE_OD0;
35         if (pinmode_od0_val){
36                 pinmode_od0 |= CAN1_RX_BIT;
37                 pinmode_od0 |= CAN1_TX_BIT;
38         }
39         else{
40                 pinmode_od0 &= ~CAN1_RX_BIT;
41                 pinmode_od0 &= ~CAN1_TX_BIT;
42         }
43         PINMODE_OD0 = pinmode_od0;
44         
45
46 }
47
48 void CAN_send(canmsg_t* msg){
49
50         uint32_t data;
51         uint32_t i;
52
53         // check status of TB1
54         while (!(CAN1SR & (1<<2))){}
55         
56         CAN1TFI1 &= ~0x000F0000;
57         CAN1TFI1 |= (msg->length)<<16;
58
59         // EXT frame
60         if(msg->flags & MSG_EXT)
61                 CAN1TFI1 |= (1<<31);
62         else
63                 CAN1TFI1 &= ~(1<<31);
64                 
65         // RTR frame
66         if(msg->flags & MSG_RTR)
67                 CAN1TFI1 |= (1<<30);
68         else
69                 CAN1TFI1 &= ~(1<<30);
70
71         // write CAN ID
72         CAN1TID1 = msg->id;
73
74         // write first 4 data bytes
75
76         data=0;
77         for(i=0; i<4; i++)
78                 data |= (msg->data[i])<<(i*8);
79
80         CAN1TDA1 = data;
81
82         // write second 4 data bytes
83
84         data=0;
85         for(i=4; i<8; i++)
86                 data |= (msg->data[i])<<((i-4)*8);
87                 CAN1TDB1 = data;
88
89         // write transmission request
90         CAN1CMR = 0x21;
91
92 }
93
94 void CAN_setBusTiming(uint32_t baudrate){
95
96         uint32_t PCLK_CAN;
97         uint32_t res;
98
99         uint8_t tq_numb; // number of time quantum
100         uint8_t TSEG1, TSEG2;
101         uint8_t BRP;
102         uint8_t SJW;
103         uint8_t SAM;
104         uint8_t div;
105
106         // 0 = the bus is sampled once
107         SAM = 0;
108
109         // the Synchronization Jump Width (this value plus one) 
110         SJW = 3;
111
112         // get clock divide for CAN1    
113         div = __mfld2val(PCLK_CAN1_MASK, PCLKSEL0);
114         switch(div){
115                 case 0:
116                         div = 4;
117                         break;
118                 case 1:
119                         div = 1;
120                         break;
121                 case 2:
122                         div = 2;
123                         break;
124                 case 3:
125                         // only for CAN, for other peripherials '11' value means div=8
126                         div = 6;
127                         break;
128         }
129
130
131         PCLK_CAN = system_frequency / div;
132
133         res = PCLK_CAN / baudrate;
134
135
136         // calculation of tq_numb - number of time quantum (must be in <8,25>)
137         // tq_numb = TSEG1 + TSEG2 + 3
138
139         for(tq_numb=25; tq_numb>=8; tq_numb--){
140                 
141                 if ((res%tq_numb)==0){
142                 
143                         // Baud Rate Prescaler. The PCLK clock is divided by (this value plus one) to produce the CAN clock.
144                         BRP = (res / tq_numb) - 1;
145
146                         // sync. segment allways 1 tq
147                         tq_numb--;
148
149                         // number of tq from the sample point to the next nominal Sync. point (this value plus one)                     
150                         TSEG2 = (tq_numb/3) - 1;
151
152                         // number of tq from Sync. point to the sample point (this value plus one)                      
153                         TSEG1 = tq_numb - (tq_numb/3) - 1;
154
155                         break;
156                 }
157         }
158
159         CAN1BTR = ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0));
160
161 }
162
163 void CAN_init(uint32_t baudrate)
164 {
165         uint32_t tmp;
166         uint32_t pclksel0;
167         uint32_t val;
168         
169
170         // configure CAN1 pins 
171         CAN_configPin();
172
173         // turn on power and clock for CAN1 
174         PCONP |= PCCAN1;
175         
176         // set clock divide for CAN1 
177
178         val = 0x00; // 00       PCLK_peripheral = CCLK/4 
179         pclksel0 = PCLKSEL0;
180         pclksel0 &= ~PCLK_CAN1_MASK;
181         pclksel0 &= ~PCLK_CAN2_MASK;
182         pclksel0 &= ~PCLK_ACF_MASK;
183         pclksel0 |= __val2mfld(PCLK_CAN1_MASK, val);
184         pclksel0 |= __val2mfld(PCLK_CAN2_MASK, val);
185         pclksel0 |= __val2mfld(PCLK_ACF_MASK, val);
186         PCLKSEL0 = pclksel0;
187         
188         // enter reset mode
189         CAN1MOD = 1;
190
191         // disable all CAN interrupts
192         CAN1IER = 0;
193
194         // reset value of Global Status Register (global controller status and error counters) 
195         CAN1GSR = 0x3C;
196
197         // request command to release Rx, Tx buffer and clear data overrun 
198         CAN1CMR = (1<<1)|(1<<2)|(1<<3);
199
200         // read to clear interrupt pending in Interrupt Capture Register 
201         tmp = CAN1ICR;
202
203         // set bus timing 
204         CAN_setBusTiming(baudrate);
205
206         // return to normal operating 
207         CAN1MOD = 0;
208
209         
210 }
211