]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pdk_k2g_1_0_1/packages/ti/board/diag/dcan/src/evmk2g_dcan_frame.c
Add alpha files for car
[processor-sdk/performance-audio-sr.git] / pdk_k2g_1_0_1 / packages / ti / board / diag / dcan / src / evmk2g_dcan_frame.c
1 /*
2  * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
3  * Copyright (C) 2006 Andrey Volkov, Varma Electronics
4  * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the version 2 of the GNU General Public License
8  * as published by the Free Software Foundation
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
20 /**
21  * \file   evmc66x_dcan_frame.c
22  *
23  * \brief  This file consists of wrapper functions which internally call
24  *         DCAN APIs.
25  */
27 #include "platform_internal.h"
29 #if (PLATFORM_DCAN_IN)
31 /**
32  * \brief   This function will configure a message object in DCAN message RAM as a
33  *          transmit message object.
34  *
35  * \param   baseAdd       Base Address of the DCAN Module Registers.
36  * \param   canPtr        Pointer to can_frame structure.
37  *
38 **/
39 unsigned int CANTxObjectConfig(unsigned int baseAdd, can_frame* canPtr)
40 {
41     unsigned int msgNum;
42     unsigned int idLen;
44     idLen = (canPtr->flag & CAN_EXT_FRAME) ? DCAN_29_BIT_ID : DCAN_11_BIT_ID;
46     /* Set the message valid bit */
47     DCANMsgObjValidate(baseAdd, DCAN_IF1_REG);
49     /* Set the message id of the frame to be transmitted */
50     DCANMsgIdSet(baseAdd, canPtr->id, idLen, DCAN_IF1_REG);
52     /* Set the message object direction as transmit */
53     DCANMsgDirectionSet(baseAdd, DCAN_TX_DIR, DCAN_IF1_REG);
55     /* Set the data length code */
56     DCANDataLengthCodeSet(baseAdd, canPtr->dlc, DCAN_IF1_REG);
58     /* Write data to the DCAN data registers */
59     DCANDataWrite(baseAdd, (canPtr->data), DCAN_IF1_REG);
61     /* Enable the transmit interrupt for the message object */
62     DCANMsgObjIntEnable(baseAdd, DCAN_TRANSMIT_INT, DCAN_IF1_REG);
64     /* Enable the DCAN FIFO End of block */
65     DCANFIFOEndOfBlockControl(baseAdd, DCAN_END_OF_BLOCK_ENABLE, DCAN_IF1_REG);
67     /* Get the transmit request status */
68     msgNum = DCANTxRqstStatGet(baseAdd);
70     /* Configure the command register */
71     DCANCommandRegSet(baseAdd, (DCAN_DAT_A_ACCESS | DCAN_MSG_WRITE | DCAN_TXRQST_ACCESS |
72                                 DCAN_DAT_B_ACCESS | DCAN_ACCESS_CTL_BITS |
73                                 DCAN_ACCESS_ARB_BITS), msgNum, DCAN_IF1_REG);
75     return msgNum;
76 }
78 /**
79  * \brief   This function will configure a message object in DCAN message RAM
80  *          as a receive message object.
81  *
82  * \param   baseAdd       Base Address of the DCAN Module Registers.
83  * \param   canPtr        Pointer to can_frame structure.
84  *
85 **/
86 unsigned int CANRxObjectConfig(unsigned int baseAdd, can_frame* canPtr)
87 {
88     unsigned int idLen;
89     unsigned int msgIndex;
91     msgIndex = (CAN_NUM_OF_MSG_OBJS / 2) + 1;
93     idLen = (canPtr->flag & CAN_EXT_FRAME) ? DCAN_29_BIT_ID : DCAN_11_BIT_ID;
95     /* Use Acceptance mask. */
96     DCANUseAcceptanceMaskControl(baseAdd, DCAN_MASK_USED, DCAN_IF2_REG);
98     /* Configure the DCAN mask registers for acceptance filtering. */
99     DCANMsgObjectMskConfig(baseAdd, DCAN_IDENTIFIER_MSK(canPtr->msk,
100                            DCAN_ID_MSK_11_BIT), DCAN_MSK_MSGDIR_DISABLE,
101                            DCAN_MSK_EXT_ID_DISABLE, DCAN_IF2_REG);
103     /* Set the message valid bit */
104     DCANMsgObjValidate(baseAdd, DCAN_IF2_REG);
106     /* Set the message id of the frame to be received */
107     DCANMsgIdSet(baseAdd, canPtr->id, idLen, DCAN_IF2_REG);
109     /* Set the message object direction as receive */
110     DCANMsgDirectionSet(baseAdd, DCAN_RX_DIR, DCAN_IF2_REG);
112     /* Enable the receive interrupt for the message object */
113     DCANMsgObjIntEnable(baseAdd, DCAN_RECEIVE_INT, DCAN_IF2_REG);
115     /* Enable the FIFO end of block */
116     DCANFIFOEndOfBlockControl(baseAdd, DCAN_END_OF_BLOCK_ENABLE, DCAN_IF2_REG);
118     /* Check for the message valid status for receive objects */
119     while((DCANMsgValidStatusGet(baseAdd, msgIndex)) &&
120           (msgIndex <= (CAN_NUM_OF_MSG_OBJS - 1)))
121     {
122         msgIndex++;
123     }
125     /* Configure the command register */
126     DCANCommandRegSet(baseAdd, (DCAN_ACCESS_CTL_BITS | DCAN_MSG_WRITE |
127                       DCAN_ACCESS_MSK_BITS | DCAN_ACCESS_ARB_BITS),
128                       msgIndex, DCAN_IF2_REG);
130     return msgIndex;
133 /**
134  * \brief   Read data from a message object.
135  *
136  * \param   baseAdd       Base Address of the DCAN Module Registers.
137  * \param   msgNum        Message object number.
138  * \param   data          Pointer to an unsigned integer. Used to fetch data
139  *                        bytes from data registers.
140  * \param   ifReg         Interface register set used.
141  *
142 */
143 void CANReadMsgObjData(unsigned int baseAdd, unsigned int msgNum,
144                        unsigned int* data, unsigned int ifReg)
146     /* Read a message object from CAN message RAM to Interface register */
147     DCANCommandRegSet(baseAdd, (DCAN_DAT_A_ACCESS | DCAN_DAT_B_ACCESS |
148                                 DCAN_TXRQST_ACCESS | DCAN_CLR_INTPND |
149                                 DCAN_ACCESS_CTL_BITS | DCAN_ACCESS_ARB_BITS |
150                                 DCAN_ACCESS_MSK_BITS | DCAN_MSG_READ),
151                                 msgNum, ifReg);
153     /* Clear the NewData bit */
154     DCANNewDataControl(baseAdd, DCAN_NEW_DAT_CLR, ifReg);
156     /* Read data bytes from interface register */
157     DCANDataRead(baseAdd, data, ifReg);
160 /**
161  * \brief   This function should be used to clear the interrupt pending status
162  *          of receive objects after a new message is received. This will clear
163  *          the IntPnd status of the message object represented by msgNum.
164  *
165  * \param   baseAdd       Base Address of the DCAN Module Registers.
166  * \param   msgNum        Message object number.
167  * \param   ifReg         Interface register set used.
168  *
169 **/
170 void CANClrIntPndStat(unsigned int baseAdd, unsigned int msgNum,
171                       unsigned int ifReg)
173     /* Clear the IntPnd bit of DCAN_IFMCTL register */
174     DCANClrIntPnd(baseAdd, ifReg);
176     /* Set the ClrIntPnd bit of DCAN_IFCMD register */
177     DCANCommandRegSet(baseAdd, DCAN_CLR_INTPND, msgNum, ifReg);
181 /**
182  * \brief   This function can be used by the user to validate a message object.
183  *
184  * \param   baseAdd       Base Address of the DCAN Module Registers.
185  * \param   msgNum        Message object number.
186  * \param   ifReg         Interface register set used.
187  *
188 **/
189 void CANValidateMsgObject(unsigned int baseAdd, unsigned int msgNum,
190                           unsigned int ifReg)
192     /* Set the MsgVal bit of DCAN_IFARB register */
193     DCANMsgObjValidate(baseAdd, ifReg);
195     /* Set the Arb bit of DCAN_IFCMD register */
196     DCANCommandRegSet(baseAdd, (DCAN_ACCESS_ARB_BITS | DCAN_MSG_WRITE),
197                       msgNum, ifReg);
200 /**
201  * \brief   This function can be used by the user to invalidate a message
202  *          object.
203  *
204  * \param   baseAdd       Base Address of the DCAN Module Registers.
205  * \param   msgNum        Message object number.
206  * \param   ifReg         Interface register set used.
207  *
208 **/
209 void CANInValidateMsgObject(unsigned int baseAdd, unsigned int msgNum,
210                             unsigned int ifReg)
212     /* Clear the MsgVal bit of DCAN_IFARB register */
213     DCANMsgObjInvalidate(baseAdd, ifReg);
215     /* Set the Arb bit of DCAN_IFCMD register */
216     DCANCommandRegSet(baseAdd, (DCAN_ACCESS_ARB_BITS | DCAN_MSG_WRITE),
217                       msgNum, ifReg);
220 /**
221  * \brief   This function can be used to disable the transmit interrupt of a
222  *          message object.
223  *
224  * \param   baseAdd       Base Address of the DCAN Module Registers.
225  * \param   msgNum        Message object number.
226  * \param   ifReg         Interface register set used.
227  *
228 **/
229 void CANTxIntDisable(unsigned int baseAdd, unsigned int msgNum,
230                      unsigned int ifReg)
232     /* Disable the message object transmit interrupt */
233     DCANMsgObjIntDisable(baseAdd, DCAN_TRANSMIT_INT, ifReg);
235     /* Set the CTL bit of the command register */
236     DCANCommandRegSet(baseAdd, (DCAN_ACCESS_CTL_BITS | DCAN_MSG_WRITE),
237                       msgNum, ifReg);
240 /**
241  * \brief   This function can be used to disable the receive interrupt of a
242  *          message object.
243  *
244  * \param   baseAdd       Base Address of the DCAN Module Registers.
245  * \param   msgNum        Message object number.
246  * \param   ifReg         Interface register set used.
247  *
248 **/
249 void CANRxIntDisable(unsigned int baseAdd, unsigned int msgNum,
250                      unsigned int ifReg)
252     /* Disable the message object receive interrupt */
253     DCANMsgObjIntDisable(baseAdd, DCAN_RECEIVE_INT, ifReg);
255     /* Set the CTL bit of the command register */
256     DCANCommandRegSet(baseAdd, (DCAN_ACCESS_CTL_BITS | DCAN_MSG_WRITE),
257                       msgNum, ifReg);
260 /**
261  * \brief   This function can be used to update the data bytes of a transmit
262  *          object and set TxRqst for this message object.
263  *
264  * \param   baseAdd       Base Address of the DCAN Module Registers.
265  * \param   dataPtr       Pointer to unsigned integer. Used to write data
266  *                        bytes to data registers.
267  * \param   msgNum        Message object number.
268  * \param   ifReg         Interface register set used.
269  *
270 **/
271 void CANUpdateDataBytes(unsigned int baseAdd, unsigned int* dataPtr,
272                         unsigned int msgNum, unsigned int ifReg)
274     /* Populate the data bytes in the data registers */
275     DCANDataWrite(baseAdd, dataPtr, ifReg);
277     /* Set the DataA, DataB, TxRqst and WR of the IF_CMD register */
278     DCANCommandRegSet(baseAdd, (DCAN_DAT_A_ACCESS | DCAN_DAT_B_ACCESS |
279                                 DCAN_TXRQST_ACCESS | DCAN_MSG_WRITE),
280                                 msgNum, ifReg);
283 /**
284  * \brief   This function takes I/P Clk frequency, required bit-rate on the
285  *          CAN bus and calculates the value to be programmed to BTR register
286  *          and sends the BTR value to 'DCANBitTimingConfig' API.
287  *
288  * \param   baseAdd       Base Address of the DCAN Module Registers.
289  * \param   clkFreq       I/P clock frequency to DCAN controller.
290  * \param   bitRate       Required bit-rate on the CAN bus.
291  *
292  * \return  Returns the error value if error is present.
293  *
294 **/
295 unsigned int CANSetBitTiming(unsigned int baseAdd, unsigned int clkFreq,
296                              unsigned int bitRate)
298     unsigned int errVal = 0, btrValue = 0, tSeg1 = 0, tSeg2 = 0;
299     struct _dcan_bittiming bit_time_values;
300     struct _dcan_hw_params *btc;
301     struct _dcan_bittiming *bt;
303     static struct _dcan_hw_params dcan_hw_params = {
304     /* tseg1Min = */ 1,
305     /* tseg1Max = */ 16,
306     /* tseg2Min = */ 1,
307     /* tseg2Max = */ 8,
308     /* sjwMax   = */ 4,
309     /* brpMin   = */ 1,
310     /* brpMax   = */ 1024,
311     /* brpInc   = */ 1,
312     };
314     bt = &bit_time_values;
315     btc = &dcan_hw_params;
317     bt->bitRate = bitRate;
319     errVal = CANbitTimeCalculator(btc, bt, clkFreq);
321     /* Calculate Time Segment2 value */
322     tSeg2 = (bt->phaseSeg2 - 1);
324     /* Calculate Time Segment1 value */
325     tSeg1 = (bt->phaseSeg1 + bt->propSeg - 1);
327     /* Write the BRP value */
328     btrValue |= ((bt->brp - 1) & DCAN_BTR_BRP);
330     /* Write the BRPE value */
331     btrValue |= (((bt->brp - 1) & EXTRACT_BRPE_VAL) << BRPE_SHIFT);
333     /* Write the Time Segment2 value */
334     btrValue |= ((tSeg2 << DCAN_BTR_TSEG2_SHIFT) & DCAN_BTR_TSEG2);
336     /* Write the Time Segment1 value */
337     btrValue |= ((tSeg1 << DCAN_BTR_TSEG1_SHIFT) & DCAN_BTR_TSEG1);
339     /* Set the BTR value to the DCAN bittiming register */
340     DCANBitTimingConfig(baseAdd, btrValue);
342     return errVal;
345 /**
346  * \brief   This function will calculate the bit-timing parameters for the
347  *          DCAN controller based on the input frequency and required bit-rate
348  *          on the CAN bus.
349  *
350  * \param   btc                 Pointer to _dcan_hw_params structure \n
351  * \param   bt                  Pointer to _dcan_bittiming structure \n
352  * \param   clkFreq             Clock frequency to DCAN controller in MHz \n
353  *
354  * \return  'errVal' based on the bit-rate error \n
355  *
356  **/
357 unsigned int CANbitTimeCalculator(struct _dcan_hw_params *btc,
358                                struct _dcan_bittiming *bt,
359                                unsigned int clkFreq)
361     int sampl_pt, spt_error = 1000, tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
362     int brp = 0, spt = 0, best_tseg = 0, best_brp = 0;
363     long error = 0, best_error = 1000000000;
364     unsigned int errVal = NO_BIT_RATE_ERR;
365     unsigned long rate, timeQuanta;
367     if(bt->bitRate > 800000)
368     {
369         sampl_pt = 750;
370     }
372     else if(bt->bitRate > 500000)
373     {
374         sampl_pt = 800;
375     }
377     else
378     {
379         sampl_pt = 875;
380     }
382     for(tseg = (btc->tseg1Max + btc->tseg2Max) * 2 + 1;
383         tseg >= (btc->tseg1Min + btc->tseg2Min) * 2; tseg--)
384     {
385         tsegall = 1 + tseg / 2;
386         /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
387         brp = clkFreq / (tsegall * bt->bitRate) + tseg % 2;
388         /* chose brp step which is possible in system */
389         brp = (brp / btc->brpInc) * btc->brpInc;
390         if((brp < btc->brpMin) || (brp > btc->brpMax))
391             continue;
392         rate = clkFreq / (brp * tsegall);
393         error = bt->bitRate - rate;
394         /* tseg brp biterror */
395         if(error < 0)
396             error = -error;
397         if(error > best_error)
398             continue;
399         best_error = error;
400         if(error == 0)
401         {
402             spt = canUpdatSamPt(btc, sampl_pt, tseg / 2,
403                                  &tseg1, &tseg2);
404             error = sampl_pt - spt;
405             if(error < 0)
406                 error = -error;
407             if(error > spt_error)
408                 continue;
409             spt_error = error;
410         }
411         best_tseg = tseg / 2;
412         best_brp = brp;
413         if(error == 0)
414             break;
415     }
417     if(best_error)
418     {
419         /* Error in one-tenth of a percent */
420         error = (best_error * 1000) / bt->bitRate;
421         if(error > CAN_CALC_MAX_ERROR)
422         {
423             errVal = BIT_RATE_ERR_MAX;
424         }
425         else
426         {
427             errVal = BIT_RATE_ERR_WARN;
428         }
429     }
431     /* real sample point */
432     bt->samplePnt = canUpdatSamPt(btc, sampl_pt, best_tseg,
433                                       &tseg1, &tseg2);
435     timeQuanta = best_brp * 1000000000UL;
437     bt->tq = timeQuanta;
438     bt->propSeg = tseg1 / 2;
439     bt->phaseSeg1 = tseg1 - bt->propSeg;
440     bt->phaseSeg2 = tseg2;
441     bt->sjw = 1;
442     bt->brp = best_brp;
443     /* real bit-rate */
444     bt->bitRate = clkFreq / (bt->brp * (tseg1 + tseg2 + 1));
446     return errVal;
449 /**
450  * \brief   This function will update the sampling point based on time
451  *          segment values \n
452  *
453  * \return  Updated sample point value \n
454  *
455  **/
456 int canUpdatSamPt(const struct _dcan_hw_params *ptr,
457                   int sampl_pt, int tseg, int *tseg1, int *tseg2)
459     *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
461     if(*tseg2 < ptr->tseg2Min)
462     {
463         *tseg2 = ptr->tseg2Min;
464     }
466     if(*tseg2 > ptr->tseg2Max)
467     {
468         *tseg2 = ptr->tseg2Max;
469     }
471     *tseg1 = tseg - *tseg2;
473     if (*tseg1 > ptr->tseg1Max)
474     {
475         *tseg1 = ptr->tseg1Max;
476         *tseg2 = tseg - *tseg1;
477     }
479     return(1000 * (tseg + 1 - *tseg2) / (tseg + 1));
482 #endif /* #if (PLATFORM_DCAN_IN) */