1 | /****************************************************************************
|
2 | * $Id:: main.c 5035 2010-09-24 23:48:55Z nxp12832 $
|
3 | * Project: NXP LPC11xx CAN example
|
4 | *
|
5 | * Description:
|
6 | * This file is part of the CAN and CANopen on-chip driver examples.
|
7 | *
|
8 | ****************************************************************************
|
9 | * Software that is described herein is for illustrative purposes only
|
10 | * which provides customers with programming information regarding the
|
11 | * products. This software is supplied "AS IS" without any warranties.
|
12 | * NXP Semiconductors assumes no responsibility or liability for the
|
13 | * use of the software, conveys no license or title under any patent,
|
14 | * copyright, or mask work right to the product. NXP Semiconductors
|
15 | * reserves the right to make changes in the software without
|
16 | * notification. NXP Semiconductors also make no representation or
|
17 | * warranty that such application will be suitable for the specified
|
18 | * use without further testing or modification.
|
19 | ****************************************************************************/
|
20 | #include "driver_config.h"
|
21 | #include "target_config.h"
|
22 |
|
23 | #include "rom_drivers.h"
|
24 | #include <cr_section_macros.h>
|
25 |
|
26 | #ifndef NULL
|
27 | #define NULL ((void *)0)
|
28 | #endif
|
29 |
|
30 | __BSS(RESERVED) char CAN_driver_memory[0xC0] ; // reserve 192 bytes for CAN driver
|
31 |
|
32 | ROM **rom = (ROM **)0x1fff1ff8;
|
33 |
|
34 | CAN_MSG_OBJ msg_obj;
|
35 |
|
36 | /* Initialize CAN Controller */
|
37 | uint32_t ClkInitTable[2] = {
|
38 | 0x00000000UL, // CANCLKDIV
|
39 | 0x00001C57UL // CAN_BTR
|
40 | };
|
41 |
|
42 | /* Callback function prototypes */
|
43 | void CAN_rx(uint8_t msg_obj_num);
|
44 | void CAN_tx(uint8_t msg_obj_num);
|
45 | void CAN_error(uint32_t error_info);
|
46 |
|
47 | /* CANopen Callback function prototypes */
|
48 | uint32_t CANOPEN_sdo_exp_read (uint16_t index, uint8_t subindex);
|
49 | uint32_t CANOPEN_sdo_exp_write(uint16_t index, uint8_t subindex, uint8_t *dat_ptr);
|
50 | uint8_t CANOPEN_sdo_req (uint8_t length, uint8_t *req_ptr, uint8_t *length_resp, uint8_t *resp_ptr);
|
51 |
|
52 | /* Publish CAN Callback Functions */
|
53 | CAN_CALLBACKS callbacks = {
|
54 | CAN_rx,
|
55 | CAN_tx,
|
56 | CAN_error,
|
57 | CANOPEN_sdo_exp_read,
|
58 | CANOPEN_sdo_exp_write,
|
59 | NULL,
|
60 | NULL,
|
61 | NULL
|
62 | };
|
63 |
|
64 | /* CANopen read-only (constant) Object Dictionary (OD) entries
|
65 | Used with Expidited SDO only. Lengths = 1/2/4 bytes */
|
66 | CAN_ODCONSTENTRY myConstOD [] = {
|
67 | /* index, subindex, length, value */
|
68 | { 0x1000, 0x00, 4, 0x54534554UL }, // "TEST"
|
69 | { 0x1018, 0x00, 1, 0x00000003UL },
|
70 | { 0x1018, 0x01, 4, 0x00000003UL },
|
71 | { 0x2000, 0x00, 1, (uint32_t)'M' },
|
72 | };
|
73 |
|
74 | /* Application variables used in variable OD */
|
75 | uint8_t error_register;
|
76 | uint32_t device_id;
|
77 | uint32_t fw_ver;
|
78 | uint16_t param;
|
79 |
|
80 | /* CANopen list of variable Object Dictionary (OD) entries
|
81 | Expedited SDO with length=1/2/4 bytes */
|
82 | CAN_ODENTRY myOD [] = {
|
83 | /* index, subindex, access_type | length, value_pointer */
|
84 | { 0x1001, 0x00, OD_EXP_RO | 1, (uint8_t *)&error_register },
|
85 | { 0x1018, 0x02, OD_EXP_RO | 4, (uint8_t *)&device_id },
|
86 | { 0x1018, 0x03, OD_EXP_RO | 4, (uint8_t *)&fw_ver },
|
87 | { 0x2001, 0x00, OD_EXP_RW | 2, (uint8_t *)¶m },
|
88 | };
|
89 |
|
90 | /* CANopen configuration structure */
|
91 | static const CAN_CANOPENCFG myCANopen = {
|
92 | 20, // node_id
|
93 | 5, // msgobj_rx
|
94 | 6, // msgobj_tx
|
95 | 1, // isr_handled
|
96 | sizeof(myConstOD)/sizeof(myConstOD[0]), // od_const_num
|
97 | (CAN_ODCONSTENTRY *)myConstOD, // od_const_table
|
98 | sizeof(myOD)/sizeof(myOD[0]), // od_num
|
99 | (CAN_ODENTRY *)myOD, // od_table
|
100 | };
|
101 |
|
102 | /* CAN receive callback */
|
103 | /* Function is executed by the Callback handler after
|
104 | a CAN message has been received */
|
105 | void CAN_rx(uint8_t msg_obj_num){
|
106 |
|
107 | /* Determine which CAN message has been received */
|
108 | msg_obj.msgobj = msg_obj_num;
|
109 |
|
110 | /* Now load up the msg_obj structure with the CAN message */
|
111 | (*rom)->pCAND->can_receive(&msg_obj);
|
112 |
|
113 | if (msg_obj_num == 1)
|
114 | {
|
115 | /* Simply transmit CAN frame (echo) with with ID +0x100 via buffer 2 */
|
116 | msg_obj.msgobj = 2;
|
117 | msg_obj.mode_id += 0x100;
|
118 | (*rom)->pCAND->can_transmit(&msg_obj);
|
119 | }
|
120 |
|
121 | return;
|
122 | }
|
123 |
|
124 | /* CAN transmit callback */
|
125 | /* Function is executed by the Callback handler after
|
126 | a CAN message has been transmitted */
|
127 | void CAN_tx(uint8_t msg_obj_num){
|
128 | return;
|
129 | }
|
130 |
|
131 | /* CAN error callback */
|
132 | /* Function is executed by the Callback handler after
|
133 | an error has occured on the CAN bus */
|
134 | void CAN_error(uint32_t error_info){
|
135 | return;
|
136 | }
|
137 |
|
138 | /* CAN interrupt handler */
|
139 | /* The CAN interrupt handler must be provided by the user application.
|
140 | It's function is to call the isr() API located in the ROM */
|
141 | void CAN_IRQHandler (void){
|
142 | (*rom)->pCAND->isr();
|
143 | }
|
144 |
|
145 | /* CANopen Callback for expedited read accesses */
|
146 | uint32_t CANOPEN_sdo_exp_read(uint16_t index, uint8_t subindex){
|
147 | if (index == 0x2001)
|
148 | param++;
|
149 |
|
150 | return 0; // Return 0 for successs, SDO Abort code for error
|
151 | }
|
152 |
|
153 | /* CANopen Callback for expedited write accesses */
|
154 | uint32_t CANOPEN_sdo_exp_write(uint16_t index, uint8_t subindex, uint8_t *dat_ptr){
|
155 | if ((index == 0x2001) && (*(uint16_t *)dat_ptr != 0))
|
156 | return SDO_ABORT_VALUE_RANGE;
|
157 | else
|
158 | return 0; // Return 0 for successs, SDO Abort code for error
|
159 | }
|
160 |
|
161 |
|
162 | int main(void) {
|
163 | /* Output the Clk onto the CLKOUT Pin PIO0_1 to monitor the freq on a scope */
|
164 | LPC_IOCON->PIO0_1 = (1<<0);
|
165 | /* Select the MAIN clock as the clock out selection since it's driving the core */
|
166 | LPC_SYSCON->CLKOUTCLKSEL = 3;
|
167 | /* Set CLKOUTDIV to 6 */
|
168 | LPC_SYSCON->CLKOUTDIV = 10; // CLKOUT Divider = 10
|
169 | /* Enable CLKOUT */
|
170 | LPC_SYSCON->CLKOUTUEN = 0;
|
171 | LPC_SYSCON->CLKOUTUEN = 1;
|
172 | while (!(LPC_SYSCON->CLKOUTUEN & 0x01));
|
173 |
|
174 | /* Initialize the CAN controller */
|
175 | (*rom)->pCAND->init_can(&ClkInitTable[0], 1);
|
176 |
|
177 | /* Configure the CAN callback functions */
|
178 | (*rom)->pCAND->config_calb(&callbacks);
|
179 |
|
180 | /* Initialize CANopen handler and variables */
|
181 | error_register = 0x00;
|
182 | device_id = 0xAA55AA55;
|
183 | fw_ver = 0x00010002;
|
184 | param = 33;
|
185 | (*rom)->pCAND->config_canopen((CAN_CANOPENCFG *)&myCANopen);
|
186 |
|
187 | /* Enable the CAN Interrupt */
|
188 | NVIC_EnableIRQ(CAN_IRQn);
|
189 |
|
190 | /* Send a simple one time CAN message */
|
191 | msg_obj.msgobj = 0;
|
192 | msg_obj.mode_id = 0x345;
|
193 | msg_obj.mask = 0x0;
|
194 | msg_obj.dlc = 4;
|
195 | msg_obj.data[0] = 'T'; //0x54
|
196 | msg_obj.data[1] = 'E'; //0x45
|
197 | msg_obj.data[2] = 'S'; //0x53
|
198 | msg_obj.data[3] = 'T'; //0x54
|
199 | (*rom)->pCAND->can_transmit(&msg_obj);
|
200 |
|
201 | /* Configure message object 1 to receive all 11-bit messages 0x400-0x4FF */
|
202 | msg_obj.msgobj = 1;
|
203 | msg_obj.mode_id = 0x400;
|
204 | msg_obj.mask = 0x700;
|
205 | (*rom)->pCAND->config_rxmsgobj(&msg_obj);
|
206 |
|
207 | while(1){
|
208 | __WFI(); /* Go to Sleep */
|
209 | }
|
210 | }
|