Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
53 johboh 1
/*********************************************************************
2
 *
3
 *                  Main application
4
 *
5
 *********************************************************************
88 johboh 6
 * FileName:        $HeadURL: https://svn.auml.se/svn/HomeAutomation/trunk/EmbeddedSoftware/PIC/canBoot/Source/Main.c $
7
 * Last changed:    $LastChangedDate: 2006-11-14 11:44:27 +0100 (Tue, 14 Nov 2006) $
8
 * By:              $LastChangedBy: johboh $
9
 * Revision:        $Revision: 88 $
53 johboh 10
 ********************************************************************/
11
 
12
#include <compiler.h>
13
#include <stackTasks.h>
64 johboh 14
#include <CANdefs.h>
15
#include <CAN.h>
67 johboh 16
#include <boot.h>
53 johboh 17
 
67 johboh 18
/** V E C T O R  R E M A P P I N G *******************************************/
19
 
20
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
21
void _high_ISR (void)
22
{
23
    _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm
24
}
25
 
26
#pragma code _LOW_INTERRUPT_VECTOR = 0x000018
27
void _low_ISR (void)
28
{
29
    _asm goto RM_LOW_INTERRUPT_VECTOR _endasm
30
}
31
 
32
#pragma code
33
 
34
 
53 johboh 35
#ifdef USE_CAN
36
    #include <CAN.h>
37
#endif
38
 
64 johboh 39
static CAN_PROTO_MESSAGE cm;
40
static BYTE ful=0;
41
static DWORD cnt =0;
42
 
53 johboh 43
static void mainInit(void);
64 johboh 44
static BOOL canGetPacket(void);
67 johboh 45
void TBLWT_Func(void);
46
void TBLWTPOSTINC_Func (void);
47
void TBLRD_Func(void);
53 johboh 48
 
67 johboh 49
#define TICK_SUB_COUNTER_10MS 312
50
#define PACKET_TIMEOUT 14
51
#define BOOTLOADER_INIT_TIMOUT 500
64 johboh 52
 
67 johboh 53
DWORD tickCounter = 0;
54
DWORD tickSubCounter = 0;
55
 
56
DWORD tickGet(void);
57
 
53 johboh 58
void main()
59
{
64 johboh 60
    static PROGRAM_STATE pgs = pgsWATING_START;
67 johboh 61
    static DWORD t = 0;
64 johboh 62
    static WORD programmerSid=0;
63
 
64
    static BYTE errMsg = ERR_NO_ERROR;
65
    static PROGRAM_STATE afterAckPgs = pgsWATING_START;
66
    static DWORD pgmAddress = 0;
67
    static BYTE bytesReceived = 0;
53 johboh 68
 
67 johboh 69
    DWORD tBoot;
70
 
71
    static BYTE pgmData[64];
72
 
64 johboh 73
    static BYTE tmp;
74
 
53 johboh 75
    // Inits
76
    mainInit();
77
 
78
    #ifdef USE_CAN
79
        canInit();
80
    #endif
81
 
67 johboh 82
    tBoot = tickGet();
64 johboh 83
 
84
 
85
    for(;;)
53 johboh 86
    {
67 johboh 87
        BYTE i;
64 johboh 88
        CAN_PROTO_MESSAGE outCm;
89
        BOOL hasPacket = canGetPacket();
90
 
67 johboh 91
        tickSubCounter++;
92
        if (tickSubCounter>TICK_SUB_COUNTER_10MS)
64 johboh 93
        {
67 johboh 94
            tickCounter++;
95
            tickSubCounter=0;
88 johboh 96
            ClrWdt();
64 johboh 97
        }
98
 
99
        switch(pgs)
100
        {
101
            case pgsWATING_START:
102
                // Check if there is bootloader start packet
79 johboh 103
                if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && cm.funcc==FUNCC_BOOT_INIT && ((((unsigned int)cm.data[RID_HIGH_INDEX])<<8)+cm.data[RID_LOW_INDEX])==MY_ID && cm.nid==MY_NID)
64 johboh 104
                {
105
                    // Has new start packet
106
                    pgmAddress      = (((DWORD)cm.data[ADDRU_INDEX])<<16)+(((DWORD)cm.data[ADDRH_INDEX])<<8)+((DWORD)cm.data[ADDRL_INDEX]);
107
                    programmerSid   = cm.sid;
108
                    t               = tickGet();
109
                    errMsg          = ERR_NO_ERROR;
110
                    afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
111
                    pgs             = pgsSEND_ACK;
67 johboh 112
                    // save pgm adress.
113
 
64 johboh 114
                }
115
 
67 johboh 116
                // Bootloader timeout
117
                if ((tickGet()-tBoot)>BOOTLOADER_INIT_TIMOUT)
118
                {
119
                    pgs = pgsDONE;
120
                }
64 johboh 121
            break;         
122
 
123
            case pgsSEND_ACK:
124
                // send ack
125
                outCm.funct             = FUNCT_BOOTLOADER;
126
                outCm.funcc             = FUNCC_BOOT_ACK;
127
                outCm.nid               = MY_NID;
128
                outCm.sid               = MY_ID;
129
                outCm.data_length       = 8;
130
                outCm.data[ERR_INDEX]   = errMsg;
131
                t                       = tickGet();
132
                pgs                     = afterAckPgs;
133
 
134
                while(!canSendMessage(outCm,PRIO_HIGH));
135
            break;
136
 
137
 
138
            case pgsWAIT_FIRST_PGM_PACKET:
139
                // wait for first pgm packet.
140
                if ((tickGet()-t)>PACKET_TIMEOUT)
141
                {
142
                    // Timeout, resend ack.
143
                    errMsg          = ERR_NO_ERROR;
144
                    afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
145
                    pgs             = pgsSEND_ACK;
146
                }
147
 
148
                // If programming packet...
67 johboh 149
                if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && (cm.funcc & 0x3)==FUNCC_BOOT_PGM && cm.nid==MY_NID && cm.sid==programmerSid)
64 johboh 150
                {
67 johboh 151
                    BYTE localIndex = (BYTE)((cm.funcc & 0x1C)>>2)*8;
152
 
64 johboh 153
                    // Save bytes in memory, setup start adress etc..
67 johboh 154
                    bytesReceived   = 8;       
155
                    pgmData[localIndex+0]=cm.data[0]; pgmData[localIndex+1]=cm.data[1]; pgmData[localIndex+2]=cm.data[2]; pgmData[localIndex+3]=cm.data[3];
156
                    pgmData[localIndex+4]=cm.data[4]; pgmData[localIndex+5]=cm.data[5]; pgmData[localIndex+6]=cm.data[6]; pgmData[localIndex+7]=cm.data[7];
157
 
64 johboh 158
                    pgs             = pgsWAIT_PGM_PACKET;
159
                }
160
 
161
 
162
            break;
163
 
164
 
165
            case pgsWAIT_PGM_PACKET:
166
 
167
 
168
                // If programming packet...
67 johboh 169
                if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && (cm.funcc & 0x3)==FUNCC_BOOT_PGM && cm.nid==MY_NID && cm.sid==programmerSid)
64 johboh 170
                {
67 johboh 171
                    BYTE localIndex = (BYTE)((cm.funcc & 0x1C)>>2)*8;
64 johboh 172
                    // Save bytes in memory, inc received bytes.
67 johboh 173
                    pgmData[localIndex+0]=cm.data[0]; pgmData[localIndex+1]=cm.data[1]; pgmData[localIndex+2]=cm.data[2]; pgmData[localIndex+3]=cm.data[3];
174
                    pgmData[localIndex+4]=cm.data[4]; pgmData[localIndex+5]=cm.data[5]; pgmData[localIndex+6]=cm.data[6]; pgmData[localIndex+7]=cm.data[7];
175
 
64 johboh 176
                    bytesReceived   += 8;
177
                    pgs              = pgsWAIT_PGM_PACKET;
178
                }
179
 
180
                // If adress packet (control packet)..
181
                if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && cm.funcc==FUNCC_BOOT_ADDR && cm.nid==MY_NID && cm.sid==programmerSid)
182
                {
183
                    // Send ack and goto wait first packet.
67 johboh 184
                    // save adress.
64 johboh 185
                    errMsg          = ERR_NO_ERROR;
186
                    afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
187
                    pgs             = pgsSEND_ACK;
188
                }
189
 
190
                // If end packet...
191
                if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && cm.funcc==FUNCC_BOOT_DONE && cm.nid==MY_NID && cm.sid==programmerSid)
192
                {
193
                    // write program.
194
                    // If no bytes received at all, assume end.
195
                    // If not 64 bytes received, send error ack and wait for first packet.
196
                    // If 64, write.
197
 
198
                    if (bytesReceived==0)
199
                    {
200
                        // No received, done.
201
                        errMsg          = ERR_NO_ERROR;
202
                        afterAckPgs     = pgsDONE;
203
                        pgs             = pgsSEND_ACK;
204
                    }
205
                    else if (bytesReceived!=64)
206
                    {
207
                        errMsg          = ERR_ERROR;
208
                        afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
209
                        pgs             = pgsSEND_ACK;
210
                    }
211
                    else
212
                    {
213
                        pgs              = pgsWRITE_PROGRAM;
214
                        afterAckPgs     = pgsDONE;
215
                    }
216
                }
217
 
218
                // If bytes received 64, write..
219
                if (bytesReceived==64)
220
                {
221
                    LED0_IO=~LED0_IO;
222
                    pgs              = pgsWRITE_PROGRAM;
223
                    afterAckPgs     = pgsWAIT_PGM_PACKET;
224
                    // TODO! Send ack more than once..
225
                }
226
 
227
 
228
            break;
229
 
230
 
231
            case pgsWRITE_PROGRAM:
232
 
88 johboh 233
                ClrWdt();
67 johboh 234
 
64 johboh 235
                // Write program and send ack.
67 johboh 236
 
68 johboh 237
                // Check addr limit
238
                if (pgmAddress<RM_RESET_VECTOR)
239
                {              
240
                    errMsg          = ERR_ERROR;
241
                    pgs             = pgsSEND_ACK;
242
                    //Not allowed to write here!
243
 
244
                }
245
 
67 johboh 246
                //Load Table pointer registers with base address to erase.
247
                TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
248
                TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
249
                TBLPTRL = (BYTE)(pgmAddress & 0xFF);
250
 
251
                // point to Flash program memory
252
                EECON1bits.EEPGD = 1;
253
                // access Flash program memory
254
                EECON1bits.CFGS = 0;
255
                // enable write to memory
256
                EECON1bits.WREN = 1;
257
                // enable Row Erase operation
258
                EECON1bits.FREE = 1;
259
                // disable interrupts
260
                INTCONbits.GIE = 0;
261
 
262
                // Do it!
263
                EECON2 = 0x55;
264
                EECON2 = 0xAA;
265
                EECON1bits.WR = 1;
266
 
267
                // enable interrupts
268
                INTCONbits.GIE = 1;
269
 
270
                //Load Table pointer registers with base address to program.
271
                TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
272
                TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
273
                TBLPTRL = (BYTE)(pgmAddress & 0xFF);
274
 
275
                // Load bytes
276
                for(i=0;i<63;i++)
277
                {
278
                    TABLAT=pgmData[i];
279
                    TBLWTPOSTINC_Func();
280
                }
281
                TABLAT=pgmData[63];
282
                TBLWT_Func();
283
 
284
 
285
                // point to Flash program memory
286
                EECON1bits.EEPGD = 1;
287
                // access Flash program memory
288
                EECON1bits.CFGS = 0;
289
                // enable write to memory
290
                EECON1bits.WREN = 1;
291
                // disable interrupts
292
                INTCONbits.GIE = 0;
293
 
294
                // Do it!
295
                EECON2 = 0x55;
296
                EECON2 = 0xAA;
297
                EECON1bits.WR = 1;
298
 
299
                // enable interrupts
300
                INTCONbits.GIE = 1;
301
 
302
                // disable write to memory
303
                EECON1bits.WREN = 0;
304
 
64 johboh 305
                pgmAddress     += 64;
306
                bytesReceived   = 0;
307
                errMsg          = ERR_NO_ERROR;
308
                pgs             = pgsSEND_ACK;
309
 
310
            break;
311
 
312
 
313
            case pgsDONE:
67 johboh 314
                _asm  goto RM_RESET_VECTOR _endasm
64 johboh 315
            break;
316
 
317
 
318
 
319
 
320
            default:
321
                pgs = pgsWATING_START;
322
            break;
323
        }
324
 
325
 
53 johboh 326
    }
327
}
328
 
329
 
330
/*
331
*   Function: mainInit
332
*
333
*   Input:  none
334
*   Output: none
335
*   Pre-conditions: none
336
*   Affects: Se code
337
*   Depends: none.
338
*/
339
void mainInit()
340
{
341
    LED0_TRIS=0;   
342
 
343
    // Enable internal PORTB pull-ups
344
    INTCON2bits.RBPU = 0;
345
 
346
    // Enable Interrupts
347
    INTCONbits.GIEH = 1;
348
    INTCONbits.GIEL = 1;
349
 
350
    // Enable interrupt prirority
351
    RCONbits.IPEN=1;
352
 
353
 
354
}
355
 
64 johboh 356
 
357
 
358
/// CAN-------------------------------------------------------
359
 
360
 
361
#ifdef USE_CAN
362
 
363
 
53 johboh 364
/*
64 johboh 365
*   Function: canInit
53 johboh 366
*
64 johboh 367
*   Input:  none
53 johboh 368
*   Output: none
64 johboh 369
*   Pre-conditions: none
370
*   Affects: Changes can registers.
53 johboh 371
*   Depends: none.
372
*/
64 johboh 373
void canInit()
53 johboh 374
{
64 johboh 375
    CANCON = 0x80; //request config mode
376
    while ((CANSTAT & 0xE0) != 0x80 ); //wait for config mode request
377
 
378
    // BAUD AND TQS
379
 
380
    BRGCON1=0;
381
 
382
    // Sync_Seq = 2 x TQ = 1
383
    BRGCON1bits.SJW1=0;
384
    BRGCON1bits.SJW0=1;
385
 
386
    // Setting BRP.
387
    BRGCON1=BRGCON1|CAN_BRP;
388
 
389
    // Maximum PHEG1
390
    BRGCON2bits.SEG2PHTS = 1;
391
 
392
    // Phase_Seg1 = 2 x TQ = 1
393
    BRGCON2bits.SEG1PH2 = 0;
394
    BRGCON2bits.SEG1PH1 = 0;
395
    BRGCON2bits.SEG1PH0 = 1;
396
 
397
    // Prop_Seq = 2 x TQ = 1
398
    BRGCON2bits.PRSEG2 = 0;
399
    BRGCON2bits.PRSEG1 = 0;
400
    BRGCON2bits.PRSEG0 = 1;
401
 
402
    //  Enableing bus wake-up
403
    BRGCON3bits.WAKDIS = 0;
404
 
405
    // Dont use filter when wakeup
406
    BRGCON3bits.WAKFIL = 0;
407
 
408
    // Phase_Seg2 = 2 x TQ = 1
409
    BRGCON3bits.SEG2PH2 = 0;
410
    BRGCON3bits.SEG2PH1 = 0;
411
    BRGCON3bits.SEG2PH0 = 1;
412
 
413
    ECANCON=0;
414
    ECANCONbits.MDSEL1 = 0;
415
    ECANCONbits.MDSEL0 = 1;
416
 
417
 
418
    // FILTERS AND MASKS
419
    RXB0CONbits.RXM1=1;
420
    RXB0CONbits.RXM0=0;
421
 
422
 
423
    // INTERRUPTS
424
 
425
    // Diable transmit interrupt
426
    TXBIE = 0;
427
 
428
    //rx no interrupt
429
    PIR3 = 0;
430
    PIE3 = 0;
431
 
432
 
433
    // Programmable no buffers interrupt
434
    BIE0  = 0x00;  
435
 
436
 
437
    //loopback mode or not
438
    #ifdef CAN_LOOPBACK_MODE
439
        CANCON = 0x40;//request loopback mode
440
        while ((CANSTAT & 0xE0) != 0x40 );//wait for loopback mode
441
    #else
442
        CANCON = 0x00;//request normal mode
443
        while ((CANSTAT & 0xE0) != 0x00 );//wait for normal mode
444
    #endif
445
 
53 johboh 446
}
447
 
64 johboh 448
 
449
 
450
 
451
/*
452
*   Function: canGetPacket
453
*
454
*   Input:  none
455
*   Output: none
456
*   Pre-conditions: a call to canISR and an packet is available and banked to RXB0
457
*   Affects: Calls canParse() function in main for parsing received packet.
458
*   Depends: none.
459
*/
460
BOOL canGetPacket()
461
{
462
 
463
        // Get which buffer that is ful.
464
             if (RXB0CONbits.RXFUL) { ECANCON=(ECANCON&0b00000)|0b10000;  }
465
        else if (RXB1CONbits.RXFUL) { ECANCON=(ECANCON&0b00000)|0b10001;  }
466
        else if (B0CONbits.RXFUL)   { ECANCON=(ECANCON&0b00000)|0b10010;  }
467
        else if (B1CONbits.RXFUL)   { ECANCON=(ECANCON&0b00000)|0b10011;  }
468
        else if (B2CONbits.RXFUL)   { ECANCON=(ECANCON&0b00000)|0b10100;  }
469
        else if (B3CONbits.RXFUL)   { ECANCON=(ECANCON&0b00000)|0b10101;  }
470
        else if (B4CONbits.RXFUL)   { ECANCON=(ECANCON&0b00000)|0b10110;  }
471
        else if (B5CONbits.RXFUL)   { ECANCON=(ECANCON&0b00000)|0b10111;  }
472
        else return FALSE;
473
 
474
 
475
        //RXB0SIDH 28 27 26 25 24 23 22 21
476
        //RXB0SIDL 20 19 18 xx xx xx 17 16
477
        //RXB0EIDH 15 14 13 12 11 10 09 08
478
        //RXB0EIDL 07 06 05 04 03 02 01 00
479
 
480
        //funct xx xx xx xx 28 27 26 25
481
        //funcc xx xx xx xx xx xx 24 23 22 21 20 19 18 17 16 15 
482
        //nid   xx xx 14 13 12 11 10 09 
483
        //sid   xx xx xx xx xx xx xx 08 07 06 05 04 03 02 01 00
484
 
485
 
486
        cm.funct=((RXB0SIDH & 0xF0)>>4);
487
        cm.funcc=(((WORD)(RXB0SIDH & 0x0F))<<6)+(((WORD)(RXB0SIDL & 0xE0))>>2)+(((WORD)(RXB0SIDL & 0x03))<<1)+(((WORD)(RXB0EIDH & 0x80))>>7);
488
        cm.nid=((RXB0EIDH & 0x7E)>>1);
489
        cm.sid=(((WORD)(RXB0EIDH & 0x01))<<8)+RXB0EIDL;
490
 
491
 
492
        // Data length
493
        cm.data_length=(RXB0DLCbits.DLC3<<3)+(RXB0DLCbits.DLC2<<2)+(RXB0DLCbits.DLC1<<1)+RXB0DLCbits.DLC0;
494
 
495
        // Data one bye one, for speed
496
        cm.data[0]=RXB0D0;  cm.data[1]=RXB0D1;
497
        cm.data[2]=RXB0D2;  cm.data[3]=RXB0D3;
498
        cm.data[4]=RXB0D4;  cm.data[5]=RXB0D5;
499
        cm.data[6]=RXB0D6;  cm.data[7]=RXB0D7;
500
 
501
        // Clear ful status
502
        RXB0CONbits.RXFUL=0;
503
 
504
        return TRUE;
505
}
506
 
507
 
508
/*
509
*   Function: canSendMessage
510
*
511
*   Input:  CAN_MESSAGE to send
512
*   Output: True if packet scheduled sucess, false otherwise.
513
*   Pre-conditions: canInit
514
*   Affects: ..
515
*   Depends: ..
516
*/
517
BOOL canSendMessage(CAN_PROTO_MESSAGE cm,CAN_PRIORITY prio)
518
{
519
 
520
    if ( TXB0CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00011; }
521
    if ( TXB1CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00100; }
522
    if ( TXB2CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00101; }
523
    // None of the transmit buffers were empty. 
524
    else { return FALSE;}
525
 
526
    if (prio<0 || prio>3) prio = 0;
527
 
528
 
529
        //RXB0SIDH 28 27 26 25 24 23 22 21
530
        //RXB0SIDL 20 19 18 xx xx xx 17 16
531
        //RXB0EIDH 15 14 13 12 11 10 09 08
532
        //RXB0EIDL 07 06 05 04 03 02 01 00
533
 
534
        //funct xx xx xx xx 28 27 26 25
535
        //funcc xx xx xx xx xx xx 24 23 22 21 20 19 18 17 16 15 
536
        //nid   xx xx 14 13 12 11 10 09 
537
        //sid   xx xx xx xx xx xx xx 08 07 06 05 04 03 02 01 00
538
 
539
        RXB0SIDH = (BYTE)((cm.funct & 0x0F)<<4)+(BYTE)((cm.funcc & 0x03C0)>>6);
540
        RXB0SIDL = (BYTE)((cm.funcc & 0x003F)<<2)+(BYTE)((cm.funcc & 0x0006)>>1);
541
        RXB0EIDH = (BYTE)((cm.funcc & 0x0001)<<7)+(BYTE)((cm.nid & 0x3F)<<1)+(BYTE)((cm.sid & 0x0100)>>8);
542
        RXB0EIDL = (BYTE)((cm.sid & 0x00FF));
543
 
544
        // Data length
545
        RXB0DLC = 0;
546
        if (cm.data_length>8) RXB0DLC=8; else RXB0DLC=cm.data_length;
547
 
88 johboh 548
        // NOT Remote request
549
        _asm
550
            bcf RXB0DLC, 6, 0
551
        _endasm
64 johboh 552
 
88 johboh 553
 
64 johboh 554
        // Data one bye one, for speed
555
        RXB0D0=cm.data[0];  RXB0D1=cm.data[1];
556
        RXB0D2=cm.data[2];  RXB0D3=cm.data[3];
557
        RXB0D4=cm.data[4];  RXB0D5=cm.data[5];
558
        RXB0D6=cm.data[6];  RXB0D7=cm.data[7];
559
 
560
        // set extended or not
561
        RXB0SIDLbits.EXID=1;
562
 
563
        // Priority
564
        RXB0CON = (RXB0CON & 0b11111100) | prio;
565
 
566
        // mark as redy to transmit
567
        _asm
568
            bsf RXB0CON, 3, 0
569
        _endasm
570
 
571
        return TRUE;
572
 
573
}
574
 
575
 
576
 
577
#endif //USE_CAN
67 johboh 578
 
579
 
580
 
581
 
582
void TBLRD_Func()
583
{
584
_asm
585
    TBLRD
586
_endasm
587
}
588
 
589
void TBLWT_Func()
590
{
591
_asm
592
    TBLWT
593
_endasm
594
}
595
 
596
 
597
void TBLWTPOSTINC_Func (void){
598
_asm
599
    TBLWTPOSTINC
600
_endasm
601
}
602
 
603
DWORD tickGet()
604
{
605
    return tickCounter;
606
}
607
 
608
 
609
#pragma code user = RM_RESET_VECTOR