Statistics
| Branch: | Tag: | Revision:

amiro-os / components / serial_reset / iwrap_can_mux.cpp @ 10687985

History | View | Annotate | Download (6.95 KB)

1
#include <ch.h>
2
#include <hal.h>
3
#include <string.h>  // memcpy
4
#include <chprintf.h>
5
#include <amiro/Constants.h>
6

    
7
#include <amiro/serial_reset/iwrap_can_mux.hpp>
8

    
9
using namespace amiro;
10
using namespace chibios_rt;
11

    
12
IwrapCanMux::IwrapCanMux(SerialDriver *_sd_, CANDriver *can, const uint8_t boardId)
13
  : BaseSequentialStreamInterface(),
14
    sd_(_sd_),
15
    canDriver(can)
16
{
17
    myID = boardId;
18
    queryShellID = boardId;
19
    replyShellID = boardId;
20

    
21
    resetStatus = 0;
22
    resetAddBytes = 0;
23

    
24
    txmsg.IDE = CAN_IDE_STD;
25
    txmsg.RTR = CAN_RTR_DATA;
26
    txmsg.DLC = 0;
27

    
28
    bluetoothStatus = BLUETOOTH_STATUS_START;
29
}
30

    
31
IwrapCanMux::~IwrapCanMux() {
32

    
33
};
34

    
35

    
36
/* Check bluetooth status
37
void IwrapCanMux::checkBluetoothStatus(void) {
38

39
      BluetoothUartReceiveByte(&byteData);
40
      switch (bluetoothStatus) {
41

42
        case BLUETOOTH_STATUS_START:
43
          if (byteData == BLUETOOTH_START_FRAME) {
44
            bluetoothStatus++;
45
          }
46
          break;
47

48
        case BLUETOOTH_STATUS_LINK:
49
            bluetoothLinkID = byteData;
50
            bluetoothStatus++;
51
          break;
52

53
        case BLUETOOTH_STATUS_FLAGS:
54
          if (byteData == BLUETOOTH_FLAGS) {
55
            bluetoothStatus++;
56
          } else {
57
            bluetoothStatus = BLUETOOTH_STATUS_START;
58
          }
59
          break;
60

61
        case BLUETOOTH_STATUS_LENGTH:
62
          bluetoothStatus++;
63
          bluetoothDataLength = byteData;
64
          break;
65

66
        case BLUETOOTH_STATUS_DATA:
67
          if (--bluetoothDataLength == 0) {
68
            bluetoothStatus++;
69
          }
70
          if (bluetoothLinkID == 0xFF) {
71
          } else {
72
            // read data
73
          }
74
          break;
75

76
        default:
77
          bluetoothStatus = BLUETOOTH_STATUS_START;
78
          if (byteData == ~bluetoothLinkID) {
79
            // iWRAP check
80
          }
81
          break;
82
      }
83
}
84
*/
85

    
86

    
87
/*
88
 * resets system for entering in bootloader.
89
 */
90
void IwrapCanMux::restartSystem(void) {
91
  //TODO Set reset SYS_PD_N
92
  NVIC_SystemReset();
93
}
94

    
95
/*
96
 * checks bytes for reset command sequence.
97
 * if the last byte and the following identification number of the device have been sent,
98
 * the microcontroller will be reset
99
 */
100
bool IwrapCanMux::checkByteForBLReset(uint8_t *inputs, size_t size) {
101
  /* Run throug all given bytes */
102
  for (size_t idx=0; idx < size; idx++) {
103
    uint8_t input = *(inputs+idx);
104

    
105
    /*
106
     * if the last byte of reset command sequence has not been sent yet,
107
     * check new byte and handle reset status
108
     */
109
    if (resetStatus < INPUT_BL_RESET_LENGTH) {
110
      if (input == inputBLReset[resetStatus]) {
111
        resetStatus++;
112
        if (resetStatus == INPUT_BL_RESET_LENGTH) {
113
          chprintf((BaseSequentialStream*)sd_, "\n\nDo reset ...\n\n");
114
          uint8_t ledCount;
115
          for (ledCount=0; ledCount<20; ledCount++) {
116
//            boardWriteLed(1);
117
            chThdSleepMilliseconds(100);
118
//            boardWriteLed(0);
119
            chThdSleepMilliseconds(100);
120
          }
121
          restartSystem();
122
        }
123
      } else {
124
        resetStatus = 0;
125
        resetAddBytes = 0;
126
      }
127

    
128
    /*
129
     * if the last byte of reset command sequence has been sent,
130
     * save new byte as identification number of the device which shall be flashed and
131
     * reset microcontroller
132
     */
133
    } else {
134
      inputAddBytes[resetAddBytes] = input;
135
      resetAddBytes++;
136
      if (resetAddBytes >= INPUT_BL_RESET_ADDITIONAL_BYTES) {
137
        chprintf((BaseSequentialStream*)sd_, "\n\nAt device %x: Do reset ...\n\n", input);
138
        chThdSleepMilliseconds(OFFSET_TIME_RESET_MS);
139
        restartSystem();
140
      }
141
    }
142
  }
143

    
144
  return (resetStatus > 0);
145
}
146

    
147
msg_t IwrapCanMux::sendViaCan(uint32_t id, uint8_t *inputs, size_t size) {
148
  msg_t status;
149
  txmsg.SID = (id << CAN::DEVICE_ID_SHIFT) | myID;
150
  for (size_t i=0; i<size; i+=8) {
151
    txmsg.DLC = (size < (i + 8)) ? size-i : 8;
152
    memcpy(txmsg.data8, &inputs[i], txmsg.DLC);
153
    status = canTransmit(canDriver, CAN_TX_MAILBOXES, &txmsg, TIME_INFINITE);
154
    if (status!= RDY_OK)
155
      return status;
156
  }
157

    
158
  return RDY_OK;
159
}
160

    
161
/*
162
 * Interface implementation.
163
 */
164

    
165
size_t IwrapCanMux::write(const uint8_t *bp, size_t n) {
166
  size_t size;
167

    
168
  if (myID != replyShellID) {
169
     msg_t status = sendViaCan(CAN::SHELL_REPLY_ID(replyShellID), (uint8_t *)bp, n);
170
     BaseThread::sleep(US2ST(500));
171
     size = (status == RDY_OK) ? n : 0;
172
  } else {
173
    size = sdWrite(sd_, bp, n);
174
  }
175

    
176
  return size;
177
}
178

    
179
size_t IwrapCanMux::read(uint8_t *bp, size_t n) {
180
  size_t size = sdRead(sd_, inputChar, n);
181

    
182
  checkByteForBLReset(inputChar, size);
183

    
184
  if (myID != queryShellID)
185
    sendViaCan(CAN::SHELL_QUERY_ID(queryShellID),inputChar, size);
186
  else
187
    memcpy(bp, inputChar, size);
188

    
189
  return size;
190
}
191

    
192
msg_t IwrapCanMux::put(uint8_t b) {
193
  msg_t byte;
194

    
195
  if (myID != replyShellID) {
196
    byte = sendViaCan(CAN::SHELL_REPLY_ID(replyShellID), &b, 1);
197
    BaseThread::sleep(US2ST(200));
198
  } else {
199
    byte = sdPut(sd_, b);
200
  }
201

    
202
  return byte;
203
}
204

    
205
msg_t IwrapCanMux::get(void) {
206
  msg_t byte = sdGet(sd_);
207
  uint8_t b = (uint8_t) byte;
208

    
209
  checkByteForBLReset(&b, 1);
210

    
211
  if (myID != queryShellID)
212
    sendViaCan(CAN::SHELL_QUERY_ID(queryShellID), &b, 1);
213

    
214
  return byte;
215
}
216

    
217
//----------------------------------------------------------------
218

    
219
/*
220
 * Converse data from CAN bus into input queue of serial driver.
221
 */
222

    
223
void IwrapCanMux::convCan2Serial(uint8_t *data_can, size_t n) {
224
  chSysLock();
225
  for (size_t i=0; i < n; i++)
226
     sdIncomingDataI(sd_, data_can[i]);
227
  chSysUnlock();
228
}
229

    
230
void IwrapCanMux::sendSwitchCmd(uint8_t setid) {
231

    
232
  if (myID == setid)
233
    chprintf((BaseSequentialStream*)sd_, "Stay at the same shell\n");
234
  else if (replyShellID == setid)
235
    chprintf((BaseSequentialStream*)sd_, "Switch to the own shell\n");
236
  else
237
    chprintf((BaseSequentialStream*)sd_, "Switch to the shell on board %d\n", setid);
238

    
239
  if (myID != setid) {
240

    
241
    if (replyShellID != setid)  {
242
      // To set the new remote shell via CAN bus.
243
      txmsg.SID = ((CAN::SHELL_QUERY_ID(setid)) << CAN::DEVICE_ID_SHIFT) | replyShellID;
244
      txmsg.DLC = 0;
245
      canTransmit(canDriver, CAN_ANY_MAILBOX, &txmsg, US2ST(545));
246
    }
247

    
248
    if (replyShellID == myID) {
249
      queryShellID = setid;
250
    } else {
251
      if (replyShellID == setid)
252
        // To return the own shell via CAN bus.
253
        txmsg.SID = ((CAN::SHELL_QUERY_ID(replyShellID)) << CAN::DEVICE_ID_SHIFT) | replyShellID;
254
      else
255
        // To set the serial board to the new remote shell.
256
        txmsg.SID = ((CAN::SHELL_QUERY_ID(replyShellID)) << CAN::DEVICE_ID_SHIFT) | setid;
257

    
258
      txmsg.DLC = 0;
259
      canTransmit(canDriver, CAN_ANY_MAILBOX, &txmsg, US2ST(545));
260

    
261
      replyShellID = myID;
262
    }
263
  }
264
}
265

    
266
void IwrapCanMux::rcvSwitchCmd(uint8_t setid) {
267

    
268
  if (myID == setid) {
269
    chprintf((BaseSequentialStream*)sd_, "\nReturn own shell\n\n");
270
    queryShellID = setid;
271
  } else if (myID != queryShellID) {
272
    chprintf((BaseSequentialStream*)sd_, "\nSwitch to the shell on board %d\n", setid);
273
    queryShellID = setid;
274
  } else {
275
    chprintf((BaseSequentialStream*)sd_, "\nShell shown in board %d\n\n", setid);
276
    replyShellID = setid;
277
  }
278
}