EE445M RTOS
Taken at the University of Texas Spring 2015
canpp.cpp
Go to the documentation of this file.
1 #include "canpp.hpp"
2 
3 #include "driverlib/sysctl.h"
4 #include "driverlib/gpio.h"
5 #include "driverlib/pin_map.h"
6 #include "driverlib/interrupt.h"
7 
8 #include "inc/hw_memmap.h"
9 #include "inc/hw_can.h"
10 
11 #include <stdint.h>
12 
13 #include "ctlsysctl.hpp"
14 
15 #define CAN_MSG_OBJ 1
16 
17 void can::init() {
18 
19  errors_rx = 0;
20  errors_tx = 0;
21  messages_sent = 0;
23 
24  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
26  GPIOPinConfigure(GPIO_PB4_CAN0RX);
27  GPIOPinConfigure(GPIO_PB5_CAN0TX);
28  GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5);
29 
30  CANInit(base);
31 
32  recv_sem = semaphore();
33 
34  CANBitRateSet(base, SysCtlClockGet(), 500000);
35  IntEnable(interrupt);
36  start();
37 }
38 
40 
41 can::can(memory_address_t can_base, uint32_t can_interrupt,
42  bool can_sender, uint32_t msg_length) {
43 
45  base = can_base;
46  interrupt = can_interrupt;
47 
48  init();
49 
50  switch(can_sender) {
51  case true:
52  sCANMessage.ui32MsgID = 1;
53  sCANMessage.ui32MsgIDMask = 0;
54  sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
55  sCANMessage.ui32MsgLen = msg_length;
56  break;
57  case false:
58  // Initialize a message object to be used for receiving CAN messages with
59  // any CAN ID. In order to receive any CAN ID, the ID and mask must both
60  // be set to 0, and the ID filter enabled.
61  sCANMessage.ui32MsgID = 0;
62  sCANMessage.ui32MsgIDMask = 0;
63  sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;
64  sCANMessage.ui32MsgLen = msg_length;
65  // Load the message object into the CAN peripheral. Once
66  // loaded the CAN will receive any message on the bus, and an
67  // interrupt will occur. Use message object 1 for receiving
68  // messages (this is distinct from the CAN ID).
69  CANMessageSet(base, CAN_MSG_OBJ, &sCANMessage, MSG_OBJ_TYPE_RX);
70  break;
71  default: while(1) {}
72  }
73 }
74 
76 
77  tCANBitClkParms psClkParms;
78  psClkParms.ui32SyncPropPhase1Seg = 5; /* from 2 to 16 */
79  psClkParms.ui32Phase2Seg = 2; /* from 1 to 8 */
80  psClkParms.ui32QuantumPrescaler = 1; /* from 1 to 1023 */
81  psClkParms.ui32SJW = 2; /* from 1 to 4 */
82  CANBitTimingSet(base, &psClkParms);
83 }
84 
85 void can::start() {
86 
87  CANIntEnable(base, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
88  CANEnable(base);
89 }
90 
91 void can::stop() {
92 
93  CANIntDisable(base, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
94  CANDisable(base);
95 }
96 
97 void can::error_tx() {
98 
99  ++errors_tx;
100 }
101 
102 void can::get(uint8_t *data) {
103 
104  sCANMessage.pui8MsgData = data;
105  CANMessageGet(base, 1, &sCANMessage, 0);
106  if(sCANMessage.ui32Flags & MSG_OBJ_DATA_LOST) {
107  ++errors_rx;
108  }
109 }
110 
111 void can::pack(uint8_t* dest, uint32_t data, uint8_t offset) {
112 
113  uint8_t i;
114  for(i=0; i<sizeof(data); ++i) {
115  /* todo: perfect the endian-swap */
116  *(dest+offset) = (uint8_t) (data & (0xFF << (i*4)));
117  }
118 }
119 
122 void can::transmit(uint8_t* data, uint32_t length, uint32_t id) {
123 
124  sCANMessage.ui32MsgID = id;
125  sCANMessage.ui32MsgIDMask = 0;
126  sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
127  sCANMessage.ui32MsgLen = length;
128  sCANMessage.pui8MsgData = data;
129 
130  CANMessageSet(base, CAN_MSG_OBJ, &sCANMessage, MSG_OBJ_TYPE_TX);
131 
132  /* todo: resend if errors occured */
133 }
134 
135 uint32_t can::count_message() {
136 
137  uint32_t ret;
138  switch(sender) {
139  case true: ret = ++messages_sent; break;
140  case false: ret = ++messages_received; break;
141  default: while(1) {}
142  }
143  return ret;
144 }
145 
146 uint32_t can::ack() {
147 
148  /* Read the CAN interrupt status to find the cause of the interrupt */
149  uint32_t ui32Status = CANIntStatus(base, CAN_INT_STS_CAUSE);
150  CANIntClear(base, ui32Status);
151  count_message();
152  return ui32Status;
153 }
154 
155 /* Local Variables: */
156 /* firestarter: (compile "make -k -j32 -C ~/workspace/ee445m-labs/build/") */
157 /* End: */
uint32_t errors_tx
Definition: canpp.hpp:29
uint32_t messages_sent
Definition: canpp.hpp:31
uint32_t memory_address_t
Definition: adcpp.hpp:16
virtual void start(void)
Definition: canpp.cpp:85
virtual uint32_t ack(void)
Definition: canpp.cpp:146
semaphore recv_sem
Definition: canpp.hpp:69
uint32_t errors_rx
Definition: canpp.hpp:30
void transmit(uint8_t *data, uint32_t length, uint32_t id=1)
Definition: canpp.cpp:122
tCANMsgObject sCANMessage
Definition: canpp.hpp:27
void pack(uint8_t *dest, uint32_t data, uint8_t offset=0)
Definition: canpp.cpp:111
memory_address_t base
Definition: canpp.hpp:23
const bool can_sender
Definition: move-main.cpp:58
void init(void)
Definition: canpp.cpp:17
void set_timing(void)
Definition: canpp.cpp:75
uint32_t count_message(void)
Definition: canpp.cpp:135
virtual void stop(void)
Definition: canpp.cpp:91
void error_tx(void)
Definition: canpp.cpp:97
uint32_t interrupt
Definition: canpp.hpp:24
uint32_t messages_received
Definition: canpp.hpp:32
can()
Definition: canpp.cpp:39
#define CAN_MSG_OBJ
Definition: canpp.cpp:15
static void enable_periph(uint32_t sys_periph)
Definition: ctlsysctl.hpp:24
void get(uint8_t *data)
Definition: canpp.cpp:102
bool sender
Definition: canpp.hpp:25