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