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: 2007-02-25 20:51:08 +0100 (Sun, 25 Feb 2007) $
8
 * By:              $LastChangedBy: johboh $
9
 * Revision:        $Revision: 339 $
53 johboh 10
 ********************************************************************/
11
 
12
#include <compiler.h>
13
#include <stackTasks.h>
64 johboh 14
#include <CANdefs.h>
15
#include <CAN.h>
339 johboh 16
#include <crc16.h>
67 johboh 17
#include <boot.h>
91 johboh 18
#include <funcdefs.h>
101 johboh 19
#include <EEaccess.h>
339 johboh 20
#include <reset.h>
53 johboh 21
 
67 johboh 22
/** V E C T O R  R E M A P P I N G *******************************************/
23
 
24
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
25
void _high_ISR (void)
26
{
27
    _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm
28
}
29
 
30
#pragma code _LOW_INTERRUPT_VECTOR = 0x000018
31
void _low_ISR (void)
32
{
33
    _asm goto RM_LOW_INTERRUPT_VECTOR _endasm
34
}
35
 
36
#pragma code
37
 
38
 
53 johboh 39
 
339 johboh 40
static CAN_PACKET cp;
64 johboh 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
 
101 johboh 58
static int MY_ID = DEFAULT_ID;
59
 
53 johboh 60
void main()
61
{
339 johboh 62
    static PROGRAM_STATE pgs = pgsWAITING_START;
63
    static PROGRAM_STATE pgsAckNext = pgsWAITING_START;
64
 
65
    static BYTE programmerId=0;
66
    static BYTE pgmData[64];
67
 
68
    static BOOT_TYPE ackType = btACK;
64 johboh 69
 
70
    static DWORD pgmAddress = 0;
339 johboh 71
    static DWORD newPgmAddress = 0;
72
    static DWORD tBoot;
73
    static DWORD t = 0;
67 johboh 74
 
339 johboh 75
    CAN_PACKET outCp;
67 johboh 76
 
53 johboh 77
    // Inits
78
    mainInit();
79
 
339 johboh 80
    canInit();
53 johboh 81
 
67 johboh 82
    tBoot = tickGet();
64 johboh 83
 
339 johboh 84
    // Read ID if exist.
101 johboh 85
    if (EERead(NODE_ID_EE)==NODE_HAS_ID)
86
    {
339 johboh 87
        MY_ID=EERead(NODE_ID_EE + 1);
101 johboh 88
    }
339 johboh 89
 
90
    for(t=0;t<64;t++) pgmData[t]=0x0;
64 johboh 91
 
339 johboh 92
    // Send bootloader startup
93
    outCp.type=ptPGM;
94
    outCp.pgm.class=pcCTRL;
95
    outCp.pgm.id=pctBOOTBOOT;
96
    outCp.length=1;
97
    outCp.data[0] = (isBOR()<<7)+(isLVD()<<6)+(isMCLR()<<5)+(isPOR()<<4)+(isWDTTO()<<3)+(isWDTWU()<<2)+(isWU()<<1);
98
    StatusReset();
99
    while(!canSendMessage(outCp));
260 johboh 100
 
101
    LED0_IO= 1;
101 johboh 102
 
64 johboh 103
    for(;;)
53 johboh 104
    {
67 johboh 105
        BYTE i;
339 johboh 106
        CAN_PACKET outCm;
107
        BOOL hasPacket = canGetPacket() && (cp.type == ptBOOT && cp.boot.rid == MY_ID);
64 johboh 108
 
67 johboh 109
        tickSubCounter++;
110
        if (tickSubCounter>TICK_SUB_COUNTER_10MS)
64 johboh 111
        {
67 johboh 112
            tickCounter++;
113
            tickSubCounter=0;
88 johboh 114
            ClrWdt();
64 johboh 115
        }
116
 
117
        switch(pgs)
118
        {
339 johboh 119
            case pgsWAITING_START:
120
                // Wait for first addresspacket.
121
                // Set startAddress to data[2]:[0].
122
                // Send ack. Goto next state.
123
                if (hasPacket==TRUE && cp.boot.type==btADDR)
64 johboh 124
                {
339 johboh 125
                    programmerId = cp.sid;
126
                    pgmAddress = (((DWORD)cp.data[2])<<16)+(((DWORD)cp.data[1])<<8)+((DWORD)cp.data[0]);
127
                    t = tickGet();
128
                    ackType = btACK;
129
                    pgsAckNext = pgsWAIT_FIRST_DATA;
130
                    pgs = pgsSEND_ACK;
131
                }  
64 johboh 132
 
67 johboh 133
                // Bootloader timeout
134
                if ((tickGet()-tBoot)>BOOTLOADER_INIT_TIMOUT)
135
                {
136
                    pgs = pgsDONE;
137
                }
339 johboh 138
                break;
64 johboh 139
 
140
            case pgsSEND_ACK:
141
                // send ack
339 johboh 142
                outCp.type = ptBOOT;
143
                outCp.boot.rid = programmerId;
144
                outCp.boot.type = ackType;
145
                outCp.length=0;
146
                t = tickGet();
147
                pgs = pgsAckNext;
64 johboh 148
 
339 johboh 149
                while(!canSendMessage(outCp));
150
                break;
64 johboh 151
 
152
 
339 johboh 153
 
154
            case pgsWAIT_FIRST_DATA:
155
                // Wait for first pgm packet. use offset to determine data index.
156
                // When receiving crc from host, check crc for offsets bytes.
157
 
64 johboh 158
                if ((tickGet()-t)>PACKET_TIMEOUT)
159
                {
339 johboh 160
                    // Timeout, resend ack/nack.
161
                    pgsAckNext = pgsWAIT_FIRST_DATA;
162
                    pgs = pgsSEND_ACK;
163
                }              
164
 
165
                if (hasPacket==TRUE && cp.boot.type==btPGM)
166
                {
167
                    BYTE localIndex = cp.boot.offset;
168
                    pgmData[localIndex+0]=cp.data[0]; pgmData[localIndex+1]=cp.data[1]; pgmData[localIndex+2]=cp.data[2]; pgmData[localIndex+3]=cp.data[3];
169
                    pgmData[localIndex+4]=cp.data[4]; pgmData[localIndex+5]=cp.data[5]; pgmData[localIndex+6]=cp.data[6]; pgmData[localIndex+7]=cp.data[7];
170
                    pgs = pgsWAIT_DATA_OR_CRC;
64 johboh 171
                }
172
 
339 johboh 173
                if (hasPacket==TRUE && cp.boot.type==btADDR)
64 johboh 174
                {
339 johboh 175
                    tBoot = tickGet();
176
                    pgs   = pgsWAITING_START;
64 johboh 177
                }
178
 
339 johboh 179
                if (hasPacket==TRUE && cp.boot.type==btCRC)
64 johboh 180
                {
339 johboh 181
                    pgs   = pgsWAIT_DATA_OR_CRC;
64 johboh 182
                }
183
 
339 johboh 184
                if (hasPacket==TRUE && cp.boot.type==btDONE)
64 johboh 185
                {
339 johboh 186
                    pgs = pgsDONE;
64 johboh 187
                }
339 johboh 188
 
189
 
190
                break;
191
 
192
            case pgsWAIT_DATA_OR_CRC:
193
                // Wait for pgm packet. use offset to determine data index.
194
                // When receiving crc from host, check crc for offsets bytes.
64 johboh 195
 
339 johboh 196
                if (hasPacket==TRUE && cp.boot.type==btCRC)
64 johboh 197
                {
339 johboh 198
                    WORD crc16 = (((WORD)cp.data[4])<<8)+((WORD)cp.data[3]);
199
                    WORD crc16calc = calc_crc(pgmData,64);
64 johboh 200
 
339 johboh 201
                    // check CRC.
202
                    if (crc16calc==crc16)
64 johboh 203
                    {
339 johboh 204
                        newPgmAddress = (((DWORD)cp.data[2])<<16)+(((DWORD)cp.data[1])<<8)+((DWORD)cp.data[0]);
205
                        pgsAckNext = pgsWAIT_FIRST_DATA;
206
                        pgs = pgsWRITE_DATA;
64 johboh 207
                    }
208
                    else
209
                    {
339 johboh 210
                        t = tickGet();
211
                        ackType = btNACK;
212
                        pgsAckNext = pgsWAIT_FIRST_DATA;
213
                        pgs = pgsSEND_ACK;
64 johboh 214
                    }
215
                }
339 johboh 216
 
217
                if (hasPacket==TRUE && cp.boot.type==btPGM)
218
                {
219
                    BYTE localIndex = cp.boot.offset;
220
                    pgmData[localIndex+0]=cp.data[0]; pgmData[localIndex+1]=cp.data[1]; pgmData[localIndex+2]=cp.data[2]; pgmData[localIndex+3]=cp.data[3];
221
                    pgmData[localIndex+4]=cp.data[4]; pgmData[localIndex+5]=cp.data[5]; pgmData[localIndex+6]=cp.data[6]; pgmData[localIndex+7]=cp.data[7];
222
                }
64 johboh 223
 
339 johboh 224
                if (hasPacket==TRUE && cp.boot.type==btADDR)
64 johboh 225
                {
339 johboh 226
                    tBoot = tickGet();
227
                    pgs   = pgsWAITING_START;
64 johboh 228
                }
229
 
339 johboh 230
                if (hasPacket==TRUE && cp.boot.type==btDONE)
231
                {
232
                    pgs = pgsDONE;
233
                }
64 johboh 234
 
339 johboh 235
                break;
64 johboh 236
 
237
 
339 johboh 238
            case pgsWRITE_DATA:
64 johboh 239
 
88 johboh 240
                ClrWdt();
67 johboh 241
 
64 johboh 242
                // Write program and send ack.
67 johboh 243
 
68 johboh 244
                // Check addr limit
245
                if (pgmAddress<RM_RESET_VECTOR)
339 johboh 246
                {      
247
                    ackType = btNACK;
248
                    pgsAckNext = pgsWAIT_FIRST_DATA;       
68 johboh 249
                    pgs             = pgsSEND_ACK;
250
                    //Not allowed to write here!
339 johboh 251
                    break;
68 johboh 252
                }
253
 
67 johboh 254
                //Load Table pointer registers with base address to erase.
255
                TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
256
                TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
257
                TBLPTRL = (BYTE)(pgmAddress & 0xFF);
258
 
259
                // point to Flash program memory
260
                EECON1bits.EEPGD = 1;
261
                // access Flash program memory
262
                EECON1bits.CFGS = 0;
263
                // enable write to memory
264
                EECON1bits.WREN = 1;
265
                // enable Row Erase operation
266
                EECON1bits.FREE = 1;
267
                // disable interrupts
268
                INTCONbits.GIE = 0;
269
 
270
                // Do it!
271
                EECON2 = 0x55;
272
                EECON2 = 0xAA;
273
                EECON1bits.WR = 1;
274
 
275
                // enable interrupts
276
                INTCONbits.GIE = 1;
277
 
278
                //Load Table pointer registers with base address to program.
279
                TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
280
                TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
281
                TBLPTRL = (BYTE)(pgmAddress & 0xFF);
282
 
283
                // Load bytes
284
                for(i=0;i<63;i++)
285
                {
286
                    TABLAT=pgmData[i];
339 johboh 287
                    pgmData[i]=0x0;
67 johboh 288
                    TBLWTPOSTINC_Func();
289
                }
290
                TABLAT=pgmData[63];
291
                TBLWT_Func();
292
 
293
 
294
                // point to Flash program memory
295
                EECON1bits.EEPGD = 1;
296
                // access Flash program memory
297
                EECON1bits.CFGS = 0;
298
                // enable write to memory
299
                EECON1bits.WREN = 1;
300
                // disable interrupts
301
                INTCONbits.GIE = 0;
302
 
303
                // Do it!
304
                EECON2 = 0x55;
305
                EECON2 = 0xAA;
306
                EECON1bits.WR = 1;
307
 
308
                // enable interrupts
309
                INTCONbits.GIE = 1;
310
 
311
                // disable write to memory
312
                EECON1bits.WREN = 0;
313
 
339 johboh 314
                pgmAddress     = newPgmAddress;
315
                ackType = btACK;       
64 johboh 316
                pgs             = pgsSEND_ACK;
317
 
318
            break;
319
 
320
            case pgsDONE:
339 johboh 321
                LED0_IO= 0;
67 johboh 322
                _asm  goto RM_RESET_VECTOR _endasm
64 johboh 323
            break;
324
 
325
 
326
            default:
339 johboh 327
                pgs = pgsWAITING_START;
64 johboh 328
            break;
329
        }
330
 
331
 
53 johboh 332
    }
333
}
334
 
335
 
336
/*
337
*   Function: mainInit
338
*
339
*   Input:  none
340
*   Output: none
341
*   Pre-conditions: none
342
*   Affects: Se code
343
*   Depends: none.
344
*/
345
void mainInit()
346
{
347
    LED0_TRIS=0;   
348
 
349
    // Enable internal PORTB pull-ups
350
    INTCON2bits.RBPU = 0;
351
 
352
    // Enable Interrupts
353
    INTCONbits.GIEH = 1;
354
    INTCONbits.GIEL = 1;
355
 
356
    // Enable interrupt prirority
357
    RCONbits.IPEN=1;
358
 
359
 
360
}
361
 
64 johboh 362
 
363
 
364
/// CAN-------------------------------------------------------
365
 
53 johboh 366
/*
64 johboh 367
*   Function: canInit
53 johboh 368
*
64 johboh 369
*   Input:  none
53 johboh 370
*   Output: none
64 johboh 371
*   Pre-conditions: none
372
*   Affects: Changes can registers.
53 johboh 373
*   Depends: none.
374
*/
64 johboh 375
void canInit()
53 johboh 376
{
64 johboh 377
    CANCON = 0x80; //request config mode
378
    while ((CANSTAT & 0xE0) != 0x80 ); //wait for config mode request
379
 
380
    // BAUD AND TQS
381
 
260 johboh 382
    // 500Khz@40Mhz (new by the book)
383
    BRGCON1 = 0x04;
384
    BRGCON2 = 0xD1;
385
    BRGCON3 = 0x81;
386
 
64 johboh 387
    ECANCON=0;
96 johboh 388
    ECANCONbits.MDSEL1 = 1;
389
    ECANCONbits.MDSEL0 = 0;
64 johboh 390
 
391
 
392
    // FILTERS AND MASKS
393
    RXB0CONbits.RXM1=1;
394
    RXB0CONbits.RXM0=0;
395
 
396
 
397
    // INTERRUPTS
398
 
399
    // Diable transmit interrupt
400
    TXBIE = 0;
401
 
402
    //rx no interrupt
403
    PIR3 = 0;
404
    PIE3 = 0;
405
 
406
 
407
    // Programmable no buffers interrupt
408
    BIE0  = 0x00;  
409
 
410
 
411
    //loopback mode or not
412
    #ifdef CAN_LOOPBACK_MODE
413
        CANCON = 0x40;//request loopback mode
414
        while ((CANSTAT & 0xE0) != 0x40 );//wait for loopback mode
415
    #else
416
        CANCON = 0x00;//request normal mode
417
        while ((CANSTAT & 0xE0) != 0x00 );//wait for normal mode
418
    #endif
419
 
53 johboh 420
}
421
 
64 johboh 422
 
423
 
424
 
425
/*
426
*   Function: canGetPacket
427
*
428
*   Input:  none
429
*   Output: none
430
*   Pre-conditions: a call to canISR and an packet is available and banked to RXB0
431
*   Affects: Calls canParse() function in main for parsing received packet.
432
*   Depends: none.
433
*/
434
BOOL canGetPacket()
435
{
436
 
437
        // Get which buffer that is ful.
96 johboh 438
        ECANCON=(ECANCON&0b00000)|(0b10000|(CANCON&0x0F));
439
        if (!RXB0CONbits.RXFUL) return FALSE;
440
 
260 johboh 441
 
64 johboh 442
        //RXB0SIDH 28 27 26 25 24 23 22 21
443
        //RXB0SIDL 20 19 18 xx xx xx 17 16
444
        //RXB0EIDH 15 14 13 12 11 10 09 08
445
        //RXB0EIDL 07 06 05 04 03 02 01 00
446
 
339 johboh 447
        cp.type = ((RXB0SIDH&0xC)>>6);
64 johboh 448
 
449
 
339 johboh 450
        if (cp.type==ptBOOT)
451
        {
452
            cp.boot.type  = ((RXB0SIDH&0x38)>>3);
453
            cp.boot.offset= ((RXB0SIDH&0x7)<<5)+((RXB0SIDL&0xE0)>>3)+(RXB0SIDL&0x3);
454
            cp.boot.rid   = RXB0EIDH;
455
        }
456
        else
457
        {
458
            cp.pgm.class= ((RXB0SIDH&0x3C)>>2);
459
            cp.pgm.id   = (((WORD)RXB0SIDH&0x3)<<13)+(((WORD)RXB0SIDL&0xE0)<<5)+((RXB0SIDL&0x3)<<8)+RXB0EIDH;
460
        }
461
        cp.sid   = RXB0EIDL;
64 johboh 462
 
463
 
464
        // Data length
339 johboh 465
        cp.length=(RXB0DLCbits.DLC3<<3)+(RXB0DLCbits.DLC2<<2)+(RXB0DLCbits.DLC1<<1)+RXB0DLCbits.DLC0;
64 johboh 466
 
467
        // Data one bye one, for speed
339 johboh 468
        cp.data[0]=RXB0D0;  cp.data[1]=RXB0D1;
469
        cp.data[2]=RXB0D2;  cp.data[3]=RXB0D3;
470
        cp.data[4]=RXB0D4;  cp.data[5]=RXB0D5;
471
        cp.data[6]=RXB0D6;  cp.data[7]=RXB0D7;
64 johboh 472
 
473
        // Clear ful status
474
        RXB0CONbits.RXFUL=0;
475
 
476
        return TRUE;
477
}
478
 
479
 
480
/*
481
*   Function: canSendMessage
482
*
483
*   Input:  CAN_MESSAGE to send
484
*   Output: True if packet scheduled sucess, false otherwise.
485
*   Pre-conditions: canInit
486
*   Affects: ..
487
*   Depends: ..
488
*/
339 johboh 489
BOOL canSendMessage(CAN_PACKET cp)
64 johboh 490
{
339 johboh 491
    BYTE prio = 3; 
492
 
64 johboh 493
    if ( TXB0CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00011; }
494
    if ( TXB1CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00100; }
495
    if ( TXB2CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00101; }
496
    // None of the transmit buffers were empty. 
497
    else { return FALSE;}
498
 
499
 
500
        //RXB0SIDH 28 27 26 25 24 23 22 21
501
        //RXB0SIDL 20 19 18 xx xx xx 17 16
502
        //RXB0EIDH 15 14 13 12 11 10 09 08
503
        //RXB0EIDL 07 06 05 04 03 02 01 00
504
 
339 johboh 505
        if (cp.type==ptBOOT)
506
        {
507
            RXB0SIDH = ((cp.type&0x3)<<6)+((cp.boot.type&0x7)<<3)+((cp.boot.offset&0xE0)>>5);
508
            RXB0SIDL = ((cp.boot.offset&0x1C)<<3)+(cp.boot.offset&0x3);
509
            RXB0EIDH = cp.boot.rid;
510
        }
511
        else
512
        {
513
            RXB0SIDH = ((cp.type&0x3)<<6)+((cp.pgm.class&0xF)<<2)+((cp.pgm.id&0x6000)>>13);
514
            RXB0SIDL = ((cp.pgm.id&0x1C00)>>5)+((cp.pgm.id&0x300)>>8);
515
            RXB0EIDH = (cp.pgm.id&0xFF);
516
        }
517
        RXB0EIDL = MY_ID;
64 johboh 518
 
519
        // Data length
520
        RXB0DLC = 0;
339 johboh 521
        if (cp.length>8) RXB0DLC=8; else RXB0DLC=cp.length;
64 johboh 522
 
88 johboh 523
        // NOT Remote request
524
        _asm
525
            bcf RXB0DLC, 6, 0
526
        _endasm
64 johboh 527
 
88 johboh 528
 
64 johboh 529
        // Data one bye one, for speed
339 johboh 530
        RXB0D0=cp.data[0];  RXB0D1=cp.data[1];
531
        RXB0D2=cp.data[2];  RXB0D3=cp.data[3];
532
        RXB0D4=cp.data[4];  RXB0D5=cp.data[5];
533
        RXB0D6=cp.data[6];  RXB0D7=cp.data[7];
64 johboh 534
 
535
        // set extended or not
536
        RXB0SIDLbits.EXID=1;
537
 
538
        // Priority
539
        RXB0CON = (RXB0CON & 0b11111100) | prio;
540
 
541
        // mark as redy to transmit
542
        _asm
543
            bsf RXB0CON, 3, 0
544
        _endasm
545
 
546
        return TRUE;
547
 
548
}
549
 
550
 
67 johboh 551
void TBLRD_Func()
552
{
553
_asm
554
    TBLRD
555
_endasm
556
}
557
 
558
void TBLWT_Func()
559
{
560
_asm
561
    TBLWT
562
_endasm
563
}
564
 
565
 
566
void TBLWTPOSTINC_Func (void){
567
_asm
568
    TBLWTPOSTINC
569
_endasm
570
}
571
 
572
DWORD tickGet()
573
{
574
    return tickCounter;
575
}
576
 
577
 
578
#pragma code user = RM_RESET_VECTOR