OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [common/] [current/] [src/] [hal_if.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      hal_if.c
4
//
5
//      ROM/RAM interfacing functions
6
//
7
//=============================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//=============================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   jskov
43
// Contributors:jskov, woehler, jld
44
// Date:        2000-06-07
45
//
46
//####DESCRIPTIONEND####
47
//
48
//=============================================================================
49
 
50
#include <pkgconf/hal.h>
51
 
52
#ifdef CYGPKG_KERNEL
53
# include <pkgconf/kernel.h>
54
#endif
55
 
56
#include <cyg/infra/cyg_ass.h>          // assertions
57
 
58
#include <cyg/hal/hal_arch.h>           // set/restore GP
59
 
60
#include <cyg/hal/hal_io.h>             // IO macros
61
#include <cyg/hal/hal_if.h>             // our interface
62
 
63
#include <cyg/hal/hal_diag.h>           // Diag IO
64
#include <cyg/hal/hal_misc.h>           // User break
65
 
66
#include <cyg/hal/hal_stub.h>           // stub functionality
67
 
68
#include <cyg/hal/hal_intr.h>           // hal_vsr_table and others
69
 
70
#ifdef CYGPKG_REDBOOT
71
#include <pkgconf/redboot.h>
72
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
73
#include <redboot.h>
74
#include <flash_config.h>
75
#endif
76
#ifdef CYGOPT_REDBOOT_FIS
77
#include <fis.h>
78
#endif
79
#endif
80
 
81
//--------------------------------------------------------------------------
82
 
83
externC void patch_dbg_syscalls(void * vector);
84
externC void init_thread_syscall(void * vector);
85
 
86
//--------------------------------------------------------------------------
87
// Implementations and function wrappers for monitor services
88
 
89
// flash config state queries
90
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
91
 
92
static __call_if_flash_cfg_op_fn_t flash_config_op;
93
 
94
static cyg_bool
95
flash_config_op(int op, struct cyg_fconfig *fc)
96
{
97
    cyg_bool res = false;
98
 
99
    CYGARC_HAL_SAVE_GP();
100
 
101
    switch (op) {
102
    case CYGNUM_CALL_IF_FLASH_CFG_GET:
103
        res = flash_get_config(fc->key, fc->val, fc->type);
104
        break;
105
    case CYGNUM_CALL_IF_FLASH_CFG_NEXT:
106
        res = flash_next_key(fc->key, fc->keylen, &fc->type, &fc->offset);
107
        break;
108
    case CYGNUM_CALL_IF_FLASH_CFG_SET:
109
        res = flash_set_config(fc->key, fc->val, fc->type);
110
        break;
111
    default:
112
        // nothing else supported yet - though it is expected that "set"
113
        // will fit the same set of arguments, potentially.
114
        break;
115
    }
116
 
117
    CYGARC_HAL_RESTORE_GP();
118
    return res;
119
}
120
#endif
121
 
122
#ifdef CYGOPT_REDBOOT_FIS
123
 
124
static __call_if_flash_fis_op_fn_t flash_fis_op;
125
 
126
static cyg_bool
127
flash_fis_op( int op, char *name, void *val)
128
{
129
    cyg_bool res = false;
130
    struct fis_image_desc *fis;
131
    int num;
132
 
133
    CYGARC_HAL_SAVE_GP();
134
    fis = fis_lookup(name, &num);
135
    if(fis != NULL)
136
    {
137
        switch ( op ) {
138
        case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE:
139
            *(CYG_ADDRESS *)val = fis->flash_base;
140
            res = true;
141
            break;
142
        case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE:
143
            *(unsigned long *)val = fis->size;
144
            res = true;
145
            break;
146
        case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE:
147
            *(CYG_ADDRESS *)val = fis->mem_base;
148
            res = true;
149
            break;
150
        case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT:
151
            *(CYG_ADDRESS *)val = fis->entry_point;
152
            res = true;
153
            break;
154
        case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH:
155
            *(unsigned long *)val = fis->data_length;
156
            res = true;
157
            break;
158
        case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM:
159
            *(unsigned long *)val = fis->desc_cksum;
160
            res = true;
161
            break;
162
        case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM:
163
            *(unsigned long *)val = fis->file_cksum;
164
            res = true;
165
            break;
166
        default:
167
            break;
168
        }
169
    }
170
    CYGARC_HAL_RESTORE_GP();
171
    return res;
172
}
173
 
174
#include <cyg/io/flash.h>
175
 
176
extern int __flash_init;
177
extern int fisdir_size;
178
extern int flash_block_size;
179
extern void* fis_addr;
180
#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
181
extern void* redundant_fis_addr;
182
#endif
183
extern void* fis_work_block;
184
extern int do_flash_init(void);
185
extern int fis_start_update_directory(int autolock);
186
extern int fis_update_directory(int autolock, int error);
187
 
188
static __call_if_flash_fis_op2_fn_t flash_fis_op2;
189
 
190
static int
191
flash_fis_op2( int op, unsigned int index, struct fis_table_entry *entry)
192
{
193
   int res=0;
194
   CYGARC_HAL_SAVE_GP();
195
   switch ( op ) {
196
      case CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION:
197
         res=CYG_REDBOOT_FIS_VERSION;
198
         break;
199
      case CYGNUM_CALL_IF_FLASH_FIS_INIT:
200
         __flash_init=0;  //force reinitialization
201
         res=do_flash_init();
202
         break;
203
      case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT:
204
         res=fisdir_size / sizeof(struct fis_image_desc);
205
         break;
206
      case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY:
207
         {
208
            struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block;
209
            CYG_ASSERT(entry!=0, "fis_table_entry == 0 !");
210
            memcpy(entry->name, img[index].u.name, 16);
211
            entry->flash_base=img[index].flash_base;
212
            entry->mem_base=img[index].mem_base;
213
            entry->size=img[index].size;
214
            entry->entry_point=img[index].entry_point;
215
            entry->data_length=img[index].data_length;
216
            entry->desc_cksum=img[index].desc_cksum;
217
            entry->file_cksum=img[index].file_cksum;
218
            res=0;
219
         }
220
         break;
221
      case CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE:
222
         fis_start_update_directory(1);
223
         break;
224
      case CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE:
225
         fis_update_directory(1, index);
226
         break;
227
      case CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY:
228
         {
229
            res=0;
230
            if (entry->name[0]!=0xff)
231
            {
232
               if ((entry->size==0)
233
                   || ((entry->size % flash_block_size) !=0)
234
                   || (flash_verify_addr((void*)entry->flash_base)!=0)
235
                   || (flash_verify_addr((void*)(entry->flash_base+entry->size-1))!=0)
236
                   || (entry->size < entry->data_length))
237
                  res=-1;
238
            }
239
 
240
            if (res==0)
241
            {
242
               struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block;
243
               memcpy(img[index].u.name, entry->name, 16);
244
               img[index].flash_base=entry->flash_base;
245
               img[index].mem_base=entry->mem_base;
246
               img[index].size=entry->size;
247
               img[index].entry_point=entry->entry_point;
248
               img[index].data_length=entry->data_length;
249
               img[index].desc_cksum=entry->desc_cksum;
250
               img[index].file_cksum=entry->file_cksum;
251
            }
252
         }
253
         break;
254
      default:
255
         break;
256
   }
257
   CYGARC_HAL_RESTORE_GP();
258
   return res;
259
}
260
 
261
#endif
262
 
263
//----------------------------
264
// Delay uS
265
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
266
 
267
static __call_if_delay_us_t delay_us;
268
 
269
static void
270
delay_us(cyg_int32 usecs)
271
{
272
    CYGARC_HAL_SAVE_GP();
273
#if defined(CYGPKG_KERNEL) && defined(HAL_CLOCK_READ)
274
    {
275
        cyg_uint32 start, elapsed_hal;
276
        cyg_int32 elapsed, elapsed_usec;
277
        cyg_int32 slice;
278
        cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;
279
        cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period;
280
 
281
        do {
282
            // Spin in slices of 1/2 the RTC period. Allows interrupts
283
            // time to run without messing up the algorithm. If we
284
            // spun for 1 period (or more) of the RTC, there would also
285
            // be problems figuring out when the timer wrapped.  We
286
            // may lose a tick or two for each cycle but it shouldn't
287
            // matter much.
288
 
289
            // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD
290
            // check for a value that would cause a 32 bit signed
291
            // multiply to overflow. But this also implies that just
292
            // multiplying by ticks_per_usec will yield a good
293
            // approximation.  Otherwise we need to do the full
294
            // multiply+divide to get sufficient accuracy. Note that
295
            // this test is actually constant, so the compiler will
296
            // eliminate it and only compile the branch that is
297
            // selected.
298
 
299
            if( usecs > usec_per_period/2 )
300
                slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2;
301
            else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period )
302
                slice = usecs * ticks_per_usec;
303
            else
304
            {
305
                slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
306
                slice /= usec_per_period;
307
            }
308
 
309
            HAL_CLOCK_READ(&start);
310
            do {
311
                HAL_CLOCK_READ(&elapsed_hal);
312
                elapsed = (elapsed_hal - start); // counts up!
313
                if (elapsed < 0)
314
                    elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
315
            } while (elapsed < slice);
316
 
317
            // Adjust by elapsed, not slice, since an interrupt may
318
            // have been stalling us for some time.
319
 
320
            if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
321
                elapsed_usec = elapsed / ticks_per_usec;
322
            else
323
            {
324
                elapsed_usec = elapsed * usec_per_period;
325
                elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
326
            }
327
 
328
            // It is possible for elapsed_usec to end up zero in some
329
            // circumstances and we could end up looping indefinitely.
330
            // Avoid that by ensuring that we always decrement usec by
331
            // at least 1 each time.
332
 
333
            usecs -= elapsed_usec ? elapsed_usec : 1;
334
 
335
        } while (usecs > 0);
336
    }
337
#else // CYGPKG_KERNEL
338
#ifdef HAL_DELAY_US
339
    // Use a HAL feature if defined
340
    HAL_DELAY_US(usecs);
341
#else
342
    // If no accurate delay mechanism, just spin for a while. Having
343
    // an inaccurate delay is much better than no delay at all. The
344
    // count of 10 should mean the loop takes something resembling
345
    // 1us on most CPUs running between 30-100MHz [depends on how many
346
    // instructions this compiles to, how many dispatch units can be
347
    // used for the simple loop, actual CPU frequency, etc]
348
    while (usecs-- > 0) {
349
        int i;
350
        for (i = 0; i < 10; i++);
351
    }
352
#endif // HAL_DELAY_US
353
#endif // CYGPKG_KERNEL
354
    CYGARC_HAL_RESTORE_GP();
355
}
356
#endif // CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
357
 
358
// Reset functions
359
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
360
 
361
static __call_if_reset_t reset;
362
 
363
static void
364
reset(void)
365
{
366
    CYGARC_HAL_SAVE_GP();
367
    // With luck, the platform defines some magic that will cause a hardware
368
    // reset.
369
#ifdef HAL_PLATFORM_RESET
370
    HAL_PLATFORM_RESET();
371
#endif
372
 
373
#ifdef HAL_PLATFORM_RESET_ENTRY
374
    // If that's not the case (above is an empty statement) there may
375
    // be defined an address we can jump to - and effectively
376
    // reinitialize the system. Not quite as good as a reset, but it
377
    // is often enough.
378
    goto *HAL_PLATFORM_RESET_ENTRY;
379
 
380
#else
381
#error " no RESET_ENTRY"
382
#endif
383
    CYG_FAIL("Reset failed");
384
    CYGARC_HAL_RESTORE_GP();
385
}
386
 
387
#endif
388
 
389
//------------------------------------
390
// NOP service
391
#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \
392
    defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
393
static int
394
nop_service(void)
395
{
396
    // This is the default service. It always returns false (0), and
397
    // _does not_ trigger any assertions. Clients must either cope
398
    // with the service failure or assert.
399
    return 0;
400
}
401
#endif
402
 
403
//----------------------------------
404
// Comm controls
405
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
406
 
407
#ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS
408
#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
409
  (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)
410
#else
411
#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
412
  CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
413
#endif
414
 
415
static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];
416
 
417
static int
418
set_debug_comm(int __comm_id)
419
{
420
    static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;
421
    hal_virtual_comm_table_t* __chan;
422
    int interrupt_state = 0;
423
    int res = 1, update = 0;
424
    CYGARC_HAL_SAVE_GP();
425
 
426
    CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
427
               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
428
               "Invalid channel");
429
 
430
    switch (__comm_id) {
431
    case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:
432
        if (__selected_id > 0)
433
            res = __selected_id-1;
434
        else if (__selected_id == 0)
435
            res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;
436
        else
437
            res = __selected_id;
438
        break;
439
 
440
    case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:
441
        CYGACC_CALL_IF_DEBUG_PROCS_SET(0);
442
        __selected_id = __comm_id;
443
        break;
444
 
445
    case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:
446
        __comm_id = 0;
447
        update = 1;
448
        break;
449
 
450
    default:
451
        __comm_id++;                    // skip mangler entry
452
        update = 1;
453
        break;
454
    }
455
 
456
    if (update) {
457
        // Find the interrupt state of the channel.
458
        __chan = CYGACC_CALL_IF_DEBUG_PROCS();
459
        if (__chan)
460
            interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
461
 
462
        __selected_id = __comm_id;
463
        CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]);
464
 
465
        // Set interrupt state on the new channel.
466
        __chan = CYGACC_CALL_IF_DEBUG_PROCS();
467
        if (interrupt_state)
468
            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
469
        else
470
            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
471
    }
472
 
473
    CYGARC_HAL_RESTORE_GP();
474
    return res;
475
}
476
 
477
static int
478
set_console_comm(int __comm_id)
479
{
480
    static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;
481
    int res = 1, update = 0;
482
    CYGARC_HAL_SAVE_GP();
483
 
484
    CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
485
               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
486
               "Invalid channel");
487
 
488
    switch (__comm_id) {
489
    case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:
490
        if (__selected_id > 0)
491
            res = __selected_id-1;
492
        else if (__selected_id == 0)
493
            res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;
494
        else
495
            res = __selected_id;
496
        break;
497
 
498
    case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:
499
        CYGACC_CALL_IF_CONSOLE_PROCS_SET(0);
500
        __selected_id = __comm_id;
501
        break;
502
 
503
    case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:
504
        __comm_id = 0;
505
        update = 1;
506
        break;
507
 
508
    default:
509
        __comm_id++;                    // skip mangler entry
510
        update = 1;
511
        break;
512
    }
513
 
514
    if (update) {
515
        __selected_id = __comm_id;
516
 
517
        CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]);
518
    }
519
 
520
    CYGARC_HAL_RESTORE_GP();
521
    return res;
522
}
523
#endif
524
 
525
#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG)
526
//-----------------------------------------------------------------------------
527
// GDB console output mangler (O-packetizer)
528
// COMMS init function at end.
529
 
530
// This gets called via the virtual vector console comms entry and
531
// handles O-packetization. The debug comms entries are used for the
532
// actual device IO.
533
static cyg_uint8
534
cyg_hal_diag_mangler_gdb_getc(void* __ch_data)
535
{
536
    cyg_uint8 __ch;
537
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
538
    CYGARC_HAL_SAVE_GP();
539
 
540
    __ch = CYGACC_COMM_IF_GETC(*__chan);
541
 
542
    CYGARC_HAL_RESTORE_GP();
543
 
544
    return __ch;
545
}
546
 
547
static char __mangler_line[100];
548
static int  __mangler_pos = 0;
549
 
550
static void
551
cyg_hal_diag_mangler_gdb_flush(void* __ch_data)
552
{
553
    CYG_INTERRUPT_STATE old;
554
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
555
#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
556
    int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES;
557
#endif
558
 
559
 
560
    // Nothing to do if mangler buffer is empty.
561
    if (__mangler_pos == 0)
562
        return;
563
 
564
    // Disable interrupts. This prevents GDB trying to interrupt us
565
    // while we are in the middle of sending a packet. The serial
566
    // receive interrupt will be seen when we re-enable interrupts
567
    // later.
568
#if defined(CYG_HAL_STARTUP_ROM) \
569
    || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)
570
    HAL_DISABLE_INTERRUPTS(old);
571
#else
572
    CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
573
#endif
574
 
575
#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
576
    // Only wait 500ms for data to arrive - avoid "stuck" connections
577
    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT);
578
#endif
579
 
580
    while(1)
581
    {
582
        static const char hex[] = "0123456789ABCDEF";
583
        cyg_uint8 csum = 0;
584
        char c1;
585
        int i;
586
 
587
        CYGACC_COMM_IF_PUTC(*__chan, '$');
588
        CYGACC_COMM_IF_PUTC(*__chan, 'O');
589
        csum += 'O';
590
        for( i = 0; i < __mangler_pos; i++ )
591
        {
592
            char ch = __mangler_line[i];
593
            char h = hex[(ch>>4)&0xF];
594
            char l = hex[ch&0xF];
595
            CYGACC_COMM_IF_PUTC(*__chan, h);
596
            CYGACC_COMM_IF_PUTC(*__chan, l);
597
            csum += h;
598
            csum += l;
599
        }
600
        CYGACC_COMM_IF_PUTC(*__chan, '#');
601
        CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]);
602
        CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]);
603
 
604
    nak:
605
#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
606
        if (CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, &c1) == 0) {
607
            c1 = '-';
608
            if (tries && (--tries == 0)) c1 = '+';
609
        }
610
#else
611
        c1 = CYGACC_COMM_IF_GETC(*__chan);
612
#endif
613
 
614
        if( c1 == '+' ) break;
615
 
616
        if( cyg_hal_is_break( &c1 , 1 ) ) {
617
            // Caller's responsibility to react on this.
618
            CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1);
619
            break;
620
        }
621
        if( c1 != '-' ) goto nak;
622
    }
623
 
624
    __mangler_pos = 0;
625
    // And re-enable interrupts
626
#if defined(CYG_HAL_STARTUP_ROM) \
627
    || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)
628
    HAL_RESTORE_INTERRUPTS(old);
629
#else
630
    CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
631
#endif
632
}
633
 
634
static void
635
cyg_hal_diag_mangler_gdb_putc(void* __ch_data, cyg_uint8 c)
636
{
637
    // No need to send CRs
638
    if( c == '\r' ) return;
639
 
640
    CYGARC_HAL_SAVE_GP();
641
 
642
    __mangler_line[__mangler_pos++] = c;
643
 
644
    if( c == '\n' || __mangler_pos == sizeof(__mangler_line) )
645
        cyg_hal_diag_mangler_gdb_flush(__ch_data);
646
 
647
    CYGARC_HAL_RESTORE_GP();
648
}
649
 
650
static void
651
cyg_hal_diag_mangler_gdb_write(void* __ch_data,
652
                               const cyg_uint8* __buf, cyg_uint32 __len)
653
{
654
    CYGARC_HAL_SAVE_GP();
655
 
656
    while(__len-- > 0)
657
        cyg_hal_diag_mangler_gdb_putc(__ch_data, *__buf++);
658
 
659
    CYGARC_HAL_RESTORE_GP();
660
}
661
 
662
static void
663
cyg_hal_diag_mangler_gdb_read(void* __ch_data,
664
                              cyg_uint8* __buf, cyg_uint32 __len)
665
{
666
    CYGARC_HAL_SAVE_GP();
667
 
668
    while(__len-- > 0)
669
        *__buf++ = cyg_hal_diag_mangler_gdb_getc(__ch_data);
670
 
671
    CYGARC_HAL_RESTORE_GP();
672
}
673
 
674
static int
675
cyg_hal_diag_mangler_gdb_control(void *__ch_data,
676
                                 __comm_control_cmd_t __func, ...)
677
{
678
    CYGARC_HAL_SAVE_GP();
679
 
680
    if (__func == __COMMCTL_FLUSH_OUTPUT)
681
        cyg_hal_diag_mangler_gdb_flush(__ch_data);
682
 
683
    CYGARC_HAL_RESTORE_GP();
684
    return 0;
685
}
686
 
687
// This is the COMMS init function. It gets called both by the stubs
688
// and diag init code to initialize the COMMS mangler channel table -
689
// that's all. The callers have to decide whether to actually use this
690
// channel.
691
void
692
cyg_hal_diag_mangler_gdb_init(void)
693
{
694
    hal_virtual_comm_table_t* comm;
695
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
696
 
697
    // Initialize mangler procs
698
    CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
699
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
700
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_gdb_write);
701
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_gdb_read);
702
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_gdb_putc);
703
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_gdb_getc);
704
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_gdb_control);
705
 
706
    // Restore the original console channel.
707
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
708
}
709
 
710
//-----------------------------------------------------------------------------
711
// Null console output mangler
712
// COMMS init function at end.
713
 
714
// This gets called via the virtual vector console comms entry and
715
// just forwards IO to the debug comms entries.
716
// This differs from setting the console channel to the same as the
717
// debug channel in that console output will go to the debug channel
718
// even if the debug channel is changed.
719
static cyg_uint8
720
cyg_hal_diag_mangler_null_getc(void* __ch_data)
721
{
722
    cyg_uint8 __ch;
723
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
724
    CYGARC_HAL_SAVE_GP();
725
 
726
    __ch = CYGACC_COMM_IF_GETC(*__chan);
727
 
728
    CYGARC_HAL_RESTORE_GP();
729
 
730
    return __ch;
731
}
732
 
733
 
734
static void
735
cyg_hal_diag_mangler_null_putc(void* __ch_data, cyg_uint8 c)
736
{
737
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
738
 
739
    CYGARC_HAL_SAVE_GP();
740
 
741
    CYGACC_COMM_IF_PUTC(*__chan, c);
742
 
743
    CYGARC_HAL_RESTORE_GP();
744
}
745
 
746
static void
747
cyg_hal_diag_mangler_null_write(void* __ch_data,
748
                                const cyg_uint8* __buf, cyg_uint32 __len)
749
{
750
    CYGARC_HAL_SAVE_GP();
751
 
752
    while(__len-- > 0)
753
        cyg_hal_diag_mangler_null_putc(__ch_data, *__buf++);
754
 
755
    CYGARC_HAL_RESTORE_GP();
756
}
757
 
758
static void
759
cyg_hal_diag_mangler_null_read(void* __ch_data,
760
                               cyg_uint8* __buf, cyg_uint32 __len)
761
{
762
    CYGARC_HAL_SAVE_GP();
763
 
764
    while(__len-- > 0)
765
        *__buf++ = cyg_hal_diag_mangler_null_getc(__ch_data);
766
 
767
    CYGARC_HAL_RESTORE_GP();
768
}
769
 
770
static int
771
cyg_hal_diag_mangler_null_control(void *__ch_data,
772
                                  __comm_control_cmd_t __func, ...)
773
{
774
    // Do nothing (yet).
775
    return 0;
776
}
777
 
778
// This is the COMMS init function. It gets called both by the stubs
779
// and diag init code to initialize the COMMS mangler channel table -
780
// that's all. The callers have to decide whether to actually use this
781
// channel.
782
void
783
cyg_hal_diag_mangler_null_init(void)
784
{
785
    hal_virtual_comm_table_t* comm;
786
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
787
 
788
    // Initialize mangler procs
789
    CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
790
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
791
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_null_write);
792
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_null_read);
793
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_null_putc);
794
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_null_getc);
795
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_null_control);
796
 
797
    // Restore the original console channel.
798
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
799
}
800
 
801
//-----------------------------------------------------------------------------
802
// Console IO functions that adhere to the virtual vector table semantics in
803
// order to ensure proper debug agent mangling when required.
804
//
805
externC void cyg_hal_plf_comms_init(void);
806
 
807
void
808
hal_if_diag_init(void)
809
{
810
    // This function may be called from various places and the code
811
    // should only run once.
812
    static cyg_uint8 called = 0;
813
    if (called) return;
814
    called = 1;
815
 
816
#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
817
 
818
#if defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
819
    // Use the mangler channel, which in turn uses the debug channel.
820
    CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
821
 
822
    // Initialize the mangler channel.
823
#if defined(CYGSEM_HAL_DIAG_MANGLER_GDB)
824
    cyg_hal_diag_mangler_gdb_init();
825
#elif defined(CYGSEM_HAL_DIAG_MANGLER_None)
826
    cyg_hal_diag_mangler_null_init();
827
#endif
828
 
829
#else // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN
830
 
831
    // Use an actual (raw) IO channel
832
    CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL);
833
 
834
#endif // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN
835
 
836
#endif // CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
837
}
838
 
839
void
840
hal_if_diag_write_char(char c)
841
{
842
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
843
 
844
    if (__chan)
845
        CYGACC_COMM_IF_PUTC(*__chan, c);
846
    else {
847
        __chan = CYGACC_CALL_IF_DEBUG_PROCS();
848
 
849
        // FIXME: What should be done if assertions are not enabled?
850
        // This is a bad bad situation - we have no means for diag
851
        // output; we want to hit a breakpoint to alert the developer
852
        // or something like that.
853
        CYG_ASSERT(__chan, "No valid channel set");
854
 
855
        CYGACC_COMM_IF_PUTC(*__chan, c);
856
    }
857
 
858
    // Check interrupt flag
859
    if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
860
        CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
861
        cyg_hal_user_break(0);
862
    }
863
}
864
 
865
void
866
hal_if_diag_read_char(char *c)
867
{
868
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
869
 
870
    if (__chan)
871
        *c = CYGACC_COMM_IF_GETC(*__chan);
872
    else {
873
        __chan = CYGACC_CALL_IF_DEBUG_PROCS();
874
 
875
        // FIXME: What should be done if assertions are not enabled?
876
        // This is a bad bad situation - we have no means for diag
877
        // output; we want to hit a breakpoint to alert the developer
878
        // or something like that.
879
        CYG_ASSERT(__chan, "No valid channel set");
880
 
881
        *c = CYGACC_COMM_IF_GETC(*__chan);
882
    }
883
}
884
#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
885
 
886
//=============================================================================
887
// CtrlC support
888
//=============================================================================
889
 
890
#if CYGINT_HAL_COMMON_SAVED_INTERRUPT_STATE_REQUIRED > 0
891
struct Hal_SavedRegisters *hal_saved_interrupt_state;
892
#endif
893
 
894
#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \
895
    || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
896
 
897
void
898
hal_ctrlc_isr_init(void)
899
{
900
    // A ROM monitor never enables the interrupt itself. This is left
901
    // to the (RAM) application.
902
#ifndef CYGSEM_HAL_ROM_MONITOR
903
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
904
 
905
#if 1 // Prevents crash on older stubs
906
    int v_m;
907
    // Allow only ctrl-c interrupt enabling when version in table is
908
    // below legal max and above the necessary service, and _not_
909
    // the value we set it to below.
910
    v_m = CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK;
911
    if (v_m >= CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX
912
        || v_m < CYGNUM_CALL_IF_SET_DEBUG_COMM
913
        || v_m == CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK)
914
        return;
915
 
916
    // Now trash that value - otherwise downloading an image with
917
    // builtin stubs on a board with older stubs (which will cause the
918
    // version to be set to VERSION_CALL) may cause all subsequent
919
    // runs to (wrongly) fall through to the below code.  If there is
920
    // a new stub on the board, it will reinitialize the version field
921
    // on reset.  Yes, this is a gross hack!
922
    CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK);
923
#endif
924
 
925
    // We can only enable interrupts on a valid debug channel.
926
    if (__chan)
927
        CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
928
#endif
929
}
930
 
931
cyg_uint32
932
hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
933
{
934
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
935
    int isr_ret = 0, ctrlc = 0;
936
 
937
    if (__chan) {
938
        isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data);
939
        if (ctrlc)
940
            cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state );
941
    }
942
    return isr_ret;
943
}
944
 
945
cyg_bool
946
hal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data)
947
{
948
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
949
    int gdb_vector = vector-1;
950
    int ctrlc = 0;
951
 
952
    // This check only to avoid crash on older stubs in case of unhandled
953
    // interrupts. It is a bit messy, but required in a transition period.
954
    if (__chan &&
955
        (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK ==
956
         (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK))){
957
        gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR);
958
    }
959
    if (vector == gdb_vector) {
960
        CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data);
961
        if (ctrlc) {
962
            cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state );
963
            return true;
964
        }
965
    }
966
    return false;
967
}
968
#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT || CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
969
 
970
//--------------------------------------------------------------------------
971
// Init function. It should be called from the platform initialization code.
972
// For monitor configurations it will initialize the calling interface table,
973
// for client configurations it will patch the existing table as per
974
// configuration.
975
void
976
hal_if_init(void)
977
{
978
    //**********************************************************************
979
    //
980
    // Note that if your RAM application is configured to initialize
981
    // the whole table _or_ the communication channels, you _cannot_
982
    // step through this function with the debugger. If your channel
983
    // configurations are set to the default, you should be able to
984
    // simply step over this function though (or use 'finish' once you
985
    // have entered this function if that GDB command works).
986
    // 
987
    // If you really do need to debug this code, the best approach is
988
    // to have a working RedBoot / GDB stub in ROM and then change the
989
    // hal_virtual_vector_table to reside at some other address in the
990
    // RAM configuration than that used by the ROM monitor.  Then
991
    // you'll be able to use the ROM monitor to debug the below code
992
    // and check that it does the right thing.
993
    //
994
    // Note that if you have a ROM monitor in ROM/flash which does
995
    // support virtual vectors, you should be able to disable the
996
    // option CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE. On some
997
    // targets (which predate the introduction of virtual vectors)
998
    // that option is enabled per default and needs to be explicitly
999
    // disabled when you have an updated ROM monitor.
1000
    //
1001
    //**********************************************************************
1002
 
1003
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE
1004
    {
1005
        int i;
1006
 
1007
        // Initialize tables with the NOP service.
1008
        // This should only be done for service routine entries - data
1009
        // pointers should be NULLed.
1010
        for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++)
1011
            hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service;
1012
 
1013
        // Version number
1014
        CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL
1015
            |((CYG_ADDRWORD)CYGNUM_CALL_IF_TABLE_VERSION_COMM<<CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift));
1016
    }
1017
#endif
1018
 
1019
    // Miscellaneous services with wrappers in this file.
1020
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
1021
    CYGACC_CALL_IF_RESET_SET(reset);
1022
#endif
1023
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
1024
    CYGACC_CALL_IF_DELAY_US_SET(delay_us);
1025
#endif
1026
 
1027
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
1028
    CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op);
1029
#endif
1030
 
1031
#ifdef CYGOPT_REDBOOT_FIS
1032
    CYGACC_CALL_IF_FLASH_FIS_OP_SET(flash_fis_op);
1033
    CYGACC_CALL_IF_FLASH_FIS_OP2_SET(flash_fis_op2);
1034
#endif
1035
 
1036
    // Data entries not currently supported in eCos
1037
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA
1038
    CYGACC_CALL_IF_DBG_DATA_SET(0);
1039
#endif
1040
 
1041
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_VERSION
1042
    CYGACC_CALL_IF_MONITOR_VERSION_SET(0);
1043
#endif
1044
 
1045
    // Comm controls
1046
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
1047
    {
1048
        int i, j;
1049
 
1050
        // Clear out tables with safe dummy function.
1051
        for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1; j++)
1052
            for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++)
1053
                comm_channels[j][i] = (CYG_ADDRWORD) &nop_service;
1054
 
1055
        // Set accessor functions
1056
        CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm);
1057
        CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm);
1058
 
1059
        // Initialize console/debug procs. Note that these _must_
1060
        // be set to empty before the comms init call.
1061
        set_debug_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY);
1062
        set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY);
1063
 
1064
        // Initialize channels. This used to be done in
1065
        // hal_diag_init() and the stub initHardware() functions, but
1066
        // it makes more sense to have here.
1067
        cyg_hal_plf_comms_init();
1068
 
1069
        // Always set the debug channel. If stubs are included, it is
1070
        // necessary. If no stubs are included it does not hurt and is
1071
        // likely to be required by the hal_if_diag_init code anyway
1072
        // as it may rely on it if using a mangler.
1073
        set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
1074
        // Set console channel to a safe default. hal_if_diag_init
1075
        // will override with console channel or mangler if necessary.
1076
        set_console_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
1077
    }
1078
 
1079
    // Reset console interrupt flag.
1080
    CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
1081
#endif
1082
 
1083
    // Set up services provided by clients
1084
#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT)   &&  \
1085
    ( defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \
1086
      || defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon))
1087
 
1088
    patch_dbg_syscalls( (void *)(hal_virtual_vector_table) );
1089
#endif
1090
 
1091
    // Init client services
1092
#if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT)
1093
    // Only include this code if we do not have a kernel. Otherwise
1094
    // the kernel supplies the functionality for the app we are linked
1095
    // with.
1096
 
1097
    // Prepare for application installation of thread info function in
1098
    // vector table.
1099
    init_thread_syscall( (void *)&hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_SYSCALL] );
1100
#endif
1101
 
1102
    // Finally, install async breakpoint handler if it is configured in.
1103
    // FIXME: this should probably check for STUBS instead (but code is
1104
    //        conditional on BREAK for now)
1105
#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
1106
    // Install async breakpoint handler into vector table.
1107
    CYGACC_CALL_IF_INSTALL_BPT_FN_SET(&cyg_hal_gdb_interrupt);
1108
#endif
1109
 
1110
#if 0 != CYGINT_HAL_PLF_IF_INIT
1111
    // Call platform specific initializations - should only be used
1112
    // to augment what has already been set up, etc.
1113
    plf_if_init();
1114
#endif
1115
}
1116
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.