[160] | 1 | /////////////////////////////////////////////////////////////////////////////////// |
---|
| 2 | // File : init.c |
---|
| 3 | // Date : 26/05/2012 |
---|
| 4 | // Authors : alain greiner & mohamed karaoui |
---|
| 5 | // Copyright (c) UPMC-LIP6 |
---|
| 6 | //////////////////////////////////////////////////////////////////////////////////// |
---|
| 7 | // The init.c files is part of the GIET nano-kernel. |
---|
| 8 | // This code can be used in the second phase of the boot to inititialise the kernel |
---|
| 9 | // structures and to launch one or several multi-tasks applications on a many_cores |
---|
| 10 | // hardware architecture. |
---|
| 11 | // All procs at this phase should have their MMU activated, this activation is done |
---|
| 12 | // by the boot phase, wich is responsable of constructing all the pages tables. |
---|
| 13 | //////////////////////////////////////////////////////////////////////////////////// |
---|
| 14 | |
---|
| 15 | #include <common.h> |
---|
| 16 | #include <ctx_handler.h> |
---|
| 17 | #include <sys_handler.h> |
---|
| 18 | #include <mapping_info.h> |
---|
| 19 | #include <giet_config.h> |
---|
| 20 | #include <mips32_registers.h> |
---|
| 21 | #include <irq_handler.h> |
---|
| 22 | #include <hwr_mapping.h> |
---|
| 23 | #include <mwmr.h> |
---|
| 24 | |
---|
| 25 | #define in_kinit __attribute__((section (".kinit"))) |
---|
| 26 | |
---|
| 27 | unsigned int _ptabs[GIET_NB_VSPACE_MAX]; |
---|
| 28 | |
---|
| 29 | void _tcg_init(); |
---|
| 30 | void _peri_init(); |
---|
| 31 | extern void _task_init(); |
---|
| 32 | |
---|
| 33 | in_kinit void _init() |
---|
| 34 | { |
---|
[163] | 35 | _puts("\n[INIT] Starting kernel initialisations "); |
---|
| 36 | _putw( _proctime() ); |
---|
| 37 | _puts("\n"); |
---|
[160] | 38 | |
---|
| 39 | // building tasks contexts |
---|
| 40 | _tcg_init(); |
---|
| 41 | _puts("\n[INIT] Task Contexts completed at cycle "); |
---|
| 42 | _putw( _proctime() ); |
---|
| 43 | _puts("\n"); |
---|
| 44 | |
---|
| 45 | // Initialize peripherals |
---|
| 46 | _peri_init(); |
---|
| 47 | _puts("\n[INIT] Peripherals completed at cycle "); |
---|
| 48 | _putw( _proctime() ); |
---|
| 49 | _puts("\n"); |
---|
| 50 | |
---|
| 51 | //wakeup all other processor |
---|
| 52 | mapping_header_t* header = (mapping_header_t*)&seg_mapping_base; |
---|
| 53 | header->signature = OUT_MAPPING_SIGNATURE; |
---|
| 54 | } |
---|
| 55 | |
---|
| 56 | //////////////////////////////////////////////////////////////////////////// |
---|
| 57 | // _eret() |
---|
| 58 | //////////////////////////////////////////////////////////////////////////// |
---|
| 59 | in_kinit void _eret() |
---|
| 60 | { |
---|
| 61 | asm volatile("eret \n" |
---|
| 62 | "nop"); |
---|
| 63 | } |
---|
| 64 | |
---|
| 65 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 66 | // This function initialises the task context for a given vspace. |
---|
| 67 | // There is a private context array for each vspace, indexed by the |
---|
| 68 | // (task_id, proc_id) composite index. |
---|
| 69 | // The following values are written in the task context: |
---|
| 70 | // - SP stack pointer = stack_base + stack_length |
---|
| 71 | // - RA return address = &_eret |
---|
| 72 | // - EPC start address = start_vector[task->startid] |
---|
| 73 | // - SR status register = OxFF13 |
---|
| 74 | // - TTY TTY index = base_tty_id + tty_local_id |
---|
| 75 | // - PTPR page table base address / 8K |
---|
| 76 | // - MODE mmu_mode = 0xF (TLBs and caches activated) |
---|
| 77 | // It statically allocates the task to the proper scheduler |
---|
| 78 | // (one scheduler per processor). |
---|
| 79 | //////////////////////////////////////////////////////////////////////////////// |
---|
| 80 | in_kinit void _task_map( unsigned int task_id, // global index |
---|
| 81 | unsigned int vspace_id, // global index |
---|
| 82 | unsigned int base_tty_id, |
---|
| 83 | unsigned int* start_vector ) |
---|
| 84 | { |
---|
| 85 | mapping_header_t* header = (mapping_header_t*)&seg_mapping_base; |
---|
| 86 | |
---|
| 87 | mapping_vseg_t* vseg = _get_vseg_base(header); |
---|
| 88 | mapping_task_t* task = _get_task_base(header); |
---|
| 89 | mapping_vspace_t* vspace = _get_vspace_base(header); |
---|
| 90 | |
---|
| 91 | unsigned int vseg_id; |
---|
| 92 | unsigned int loc_id; |
---|
| 93 | unsigned int proc_id; |
---|
| 94 | |
---|
| 95 | unsigned int sp; |
---|
| 96 | unsigned int ra = (unsigned int)&_eret; |
---|
| 97 | |
---|
| 98 | #if INIT_DEBUG_CTX |
---|
| 99 | _puts("\n[INIT] : task start vector "); |
---|
| 100 | _putw((unsigned int)start_vector); |
---|
| 101 | _puts("\n[INIT] : task startid "); |
---|
| 102 | _putw(task[task_id].startid); |
---|
| 103 | #endif |
---|
| 104 | unsigned int epc = start_vector[task[task_id].startid]; |
---|
| 105 | unsigned int tty = base_tty_id + task[task_id].ttylocid; |
---|
| 106 | unsigned int sr = 0x0000FF13; |
---|
| 107 | unsigned int mode = 0xF; |
---|
| 108 | |
---|
| 109 | unsigned int ptpr = ((unsigned int)_ptabs[vspace_id]) >> 13; |
---|
| 110 | |
---|
| 111 | // check values |
---|
| 112 | if ( task[task_id].proclocid >= NB_PROCS ) |
---|
| 113 | { |
---|
| 114 | _puts("\n[INIT ERROR] : processor index too large for task "); |
---|
| 115 | _puts( task[task_id].name ); |
---|
| 116 | _puts(" in vspace "); |
---|
| 117 | _puts( vspace[vspace_id].name ); |
---|
| 118 | _puts("\n"); |
---|
| 119 | _exit(); |
---|
| 120 | } |
---|
| 121 | if ( task[task_id].clusterid >= NB_CLUSTERS ) |
---|
| 122 | { |
---|
| 123 | _puts("\n[INIT ERROR] : cluster index too large for task "); |
---|
| 124 | _puts( task[task_id].name ); |
---|
| 125 | _puts(" in vspace "); |
---|
| 126 | _puts( vspace[vspace_id].name ); |
---|
| 127 | _puts("\n"); |
---|
| 128 | _exit(); |
---|
| 129 | } |
---|
| 130 | if ( task[task_id].vobjlocid >= vspace->vsegs ) |
---|
| 131 | { |
---|
| 132 | _puts("\n[INIT ERROR] : vseg index too large for task "); |
---|
| 133 | _puts( task[task_id].name ); |
---|
| 134 | _puts(" in vspace "); |
---|
| 135 | _puts( vspace[vspace_id].name ); |
---|
| 136 | _puts("\n"); |
---|
| 137 | _exit(); |
---|
| 138 | } |
---|
| 139 | if ( task[task_id].startid >= vspace->tasks ) |
---|
| 140 | { |
---|
| 141 | _puts("\n[INIT ERROR] : start index too large for task "); |
---|
| 142 | _puts( task[task_id].name ); |
---|
| 143 | _puts(" in vspace "); |
---|
| 144 | _puts( vspace[vspace_id].name ); |
---|
| 145 | _puts("\n"); |
---|
| 146 | _exit(); |
---|
| 147 | } |
---|
| 148 | if ( tty >= NB_TTYS ) |
---|
| 149 | { |
---|
| 150 | _puts("\n[INIT ERROR] : TTY index too large for task "); |
---|
| 151 | _puts( task[task_id].name ); |
---|
| 152 | _puts(" in vspace "); |
---|
| 153 | _puts( vspace[vspace_id].name ); |
---|
| 154 | _puts("\n"); |
---|
| 155 | _exit(); |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | // get stack pointer value |
---|
| 159 | vseg_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset; |
---|
| 160 | sp = vseg[vseg_id].vbase + vseg[vseg_id].length; |
---|
| 161 | |
---|
| 162 | // compute global processor index |
---|
| 163 | proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid; |
---|
| 164 | |
---|
| 165 | // check local task index |
---|
| 166 | loc_id = _scheduler[proc_id].tasks; |
---|
| 167 | if ( loc_id >= GIET_NB_TASKS_MAX ) |
---|
| 168 | { |
---|
| 169 | _puts("\n[INIT ERROR] : too much tasks allocated to processor "); |
---|
| 170 | _putw( proc_id ); |
---|
| 171 | _puts("\n"); |
---|
| 172 | _exit(); |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | // update number of tasks allocated to scheduler |
---|
| 176 | _scheduler[proc_id].tasks = loc_id + 1; |
---|
| 177 | |
---|
| 178 | // initializes the task context |
---|
| 179 | _scheduler[proc_id].context[loc_id][CTX_SR_ID] = sr; |
---|
| 180 | _scheduler[proc_id].context[loc_id][CTX_SP_ID] = sp; |
---|
| 181 | _scheduler[proc_id].context[loc_id][CTX_RA_ID] = ra; |
---|
| 182 | _scheduler[proc_id].context[loc_id][CTX_EPC_ID] = epc; |
---|
| 183 | _scheduler[proc_id].context[loc_id][CTX_TTY_ID] = tty; |
---|
| 184 | _scheduler[proc_id].context[loc_id][CTX_PTPR_ID] = ptpr; |
---|
| 185 | _scheduler[proc_id].context[loc_id][CTX_MODE_ID] = mode; |
---|
| 186 | |
---|
| 187 | #if INIT_DEBUG_CTX |
---|
| 188 | _puts("Task "); |
---|
| 189 | _puts( task[task_id].name ); |
---|
| 190 | _puts(" allocated to processor "); |
---|
| 191 | _putw( proc_id ); |
---|
| 192 | _puts(" / loc_id = "); |
---|
| 193 | _putw( loc_id ); |
---|
| 194 | _puts("\n"); |
---|
| 195 | |
---|
| 196 | _puts(" - SR = "); |
---|
| 197 | _putw( sr ); |
---|
| 198 | _puts(" saved at "); |
---|
| 199 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_SR_ID] ); |
---|
| 200 | _puts("\n"); |
---|
| 201 | |
---|
| 202 | _puts(" - RA = "); |
---|
| 203 | _putw( ra ); |
---|
| 204 | _puts(" saved at "); |
---|
| 205 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_RA_ID] ); |
---|
| 206 | _puts("\n"); |
---|
| 207 | |
---|
| 208 | _puts(" - SP = "); |
---|
| 209 | _putw( sp ); |
---|
| 210 | _puts(" saved at "); |
---|
| 211 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_SP_ID] ); |
---|
| 212 | _puts("\n"); |
---|
| 213 | |
---|
| 214 | _puts(" - EPC = "); |
---|
| 215 | _putw( epc ); |
---|
| 216 | _puts(" saved at "); |
---|
| 217 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_EPC_ID] ); |
---|
| 218 | _puts("\n"); |
---|
| 219 | |
---|
| 220 | _puts(" - TTY = "); |
---|
| 221 | _putw( tty ); |
---|
| 222 | _puts(" saved at "); |
---|
| 223 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_TTY_ID] ); |
---|
| 224 | _puts("\n"); |
---|
| 225 | |
---|
| 226 | _puts(" - PTPR = "); |
---|
| 227 | _putw( ptpr<<13 ); |
---|
| 228 | _puts(" saved at "); |
---|
| 229 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_PTPR_ID] ); |
---|
| 230 | _puts("\n"); |
---|
| 231 | |
---|
| 232 | _puts(" - MODE = "); |
---|
| 233 | _putw( mode ); |
---|
| 234 | _puts(" saved at "); |
---|
| 235 | _putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_MODE_ID] ); |
---|
| 236 | _puts("\n"); |
---|
| 237 | #endif |
---|
| 238 | |
---|
| 239 | } // end _task_map() |
---|
| 240 | |
---|
| 241 | /////////////////////////////////////////////////////////////////////////// |
---|
| 242 | // Initialise vobjs |
---|
| 243 | // parm: |
---|
| 244 | // vobj: the vobj to initialise |
---|
| 245 | // region_id: the vspace in wich the vobj is located or the global space(-1). |
---|
| 246 | /////////////////////////////////////////////////////////////////////////// |
---|
| 247 | void initialise_vobj(mapping_vobj_t* vobj, unsigned int region_id) |
---|
| 248 | { |
---|
| 249 | mwmr_channel_t* mwmr; |
---|
| 250 | switch(vobj->type) |
---|
| 251 | { |
---|
| 252 | |
---|
| 253 | case PTAB: |
---|
| 254 | break; |
---|
| 255 | |
---|
| 256 | case MWMR: |
---|
| 257 | // initializes MWMR channel if vseg is a MWMR |
---|
| 258 | // the channel storage capacity is (vobj->length/4 - 5) words |
---|
| 259 | mwmr = (mwmr_channel_t*)(vobj->vaddr); |
---|
| 260 | mwmr->ptw = 0; |
---|
| 261 | mwmr->ptr = 0; |
---|
| 262 | mwmr->sts = 0; |
---|
| 263 | mwmr->depth = (vobj->length>>2) - 5; |
---|
| 264 | mwmr->lock = 0; |
---|
| 265 | |
---|
| 266 | #if INIT_DEBUG_CTX |
---|
| 267 | _puts(" MWMR channel name = "); |
---|
| 268 | _puts( vobj->name); |
---|
| 269 | _puts(" MWMR channel depth = "); |
---|
| 270 | _putw( mwmr->depth ); |
---|
| 271 | _puts("\n"); |
---|
| 272 | #endif |
---|
| 273 | break; |
---|
| 274 | case ELF: |
---|
| 275 | break; |
---|
| 276 | case PERI: |
---|
| 277 | break; |
---|
| 278 | case BARRIER: |
---|
| 279 | case BUFFER: |
---|
| 280 | case LOCK: |
---|
| 281 | break;//TODO |
---|
| 282 | default: |
---|
| 283 | _puts("Unknown Ressource of type: "); |
---|
| 284 | _putw(vobj->type); |
---|
| 285 | _puts("Unknown Ressource name: "); |
---|
| 286 | _puts(vobj->name); |
---|
| 287 | _puts("\n "); |
---|
| 288 | _exit(); |
---|
| 289 | } |
---|
| 290 | } |
---|
| 291 | |
---|
| 292 | |
---|
| 293 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 294 | // |
---|
| 295 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 296 | void _set_ptpr(unsigned int vspace_id) |
---|
| 297 | { |
---|
| 298 | unsigned int ptpr = ((unsigned int)_ptabs[vspace_id]) >> 13; |
---|
| 299 | asm volatile("mtc2 %0, $0"::"r"(ptpr)); |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 303 | // This function sets the schedulers default values for all processors |
---|
| 304 | // (tasks <= 0, and current <= 0). |
---|
| 305 | // Then it scan all tasks (in all vspaces) to initialise the schedulers, |
---|
| 306 | // the tasks contexts, as defined in the mapping_info data structure. |
---|
| 307 | // A global TTY index is allocated to each task, as specified in the mapping. |
---|
| 308 | // TTY0 is reserved for the kernel. |
---|
| 309 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 310 | in_kinit void _tcg_init() |
---|
| 311 | { |
---|
| 312 | mapping_header_t* header = (mapping_header_t*)&seg_mapping_base; |
---|
| 313 | mapping_cluster_t* cluster = _get_cluster_base( header ); |
---|
| 314 | mapping_vspace_t* vspace = _get_vspace_base( header ); |
---|
| 315 | mapping_vobj_t* vobj = _get_vobj_base( header ); |
---|
| 316 | |
---|
| 317 | |
---|
| 318 | unsigned int* start_vector_base; |
---|
| 319 | |
---|
| 320 | unsigned int base_tty_id = 1; // TTY allocator |
---|
| 321 | |
---|
| 322 | unsigned int cluster_id; |
---|
| 323 | unsigned int proc_id; |
---|
| 324 | unsigned int vspace_id; |
---|
| 325 | unsigned int vobj_id; |
---|
| 326 | unsigned int task_id; |
---|
| 327 | |
---|
| 328 | _puts("\n SCHEDULLER "); |
---|
| 329 | _putw((unsigned int)_scheduler); |
---|
| 330 | _puts("\n"); |
---|
| 331 | |
---|
| 332 | // initialise the schedulers (not done by the compiler/loader) |
---|
| 333 | for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ ) |
---|
| 334 | { |
---|
| 335 | for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ ) |
---|
| 336 | { |
---|
| 337 | if ( proc_id >= NB_PROCS ) |
---|
| 338 | { |
---|
| 339 | _puts("\n[INIT ERROR] The number of processors in cluster "); |
---|
| 340 | _putw( cluster_id ); |
---|
| 341 | _puts(" is larger than NB_PROCS \n"); |
---|
| 342 | _exit(); |
---|
| 343 | } |
---|
| 344 | _scheduler[cluster_id*NB_PROCS+proc_id].tasks = 0; |
---|
| 345 | _scheduler[cluster_id*NB_PROCS+proc_id].current = 0; |
---|
| 346 | } |
---|
| 347 | } |
---|
| 348 | |
---|
| 349 | // loop on the virtual spaces and set the ptpr |
---|
| 350 | for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ ) |
---|
| 351 | { |
---|
| 352 | char found = 0; |
---|
| 353 | //initialise all vobjs |
---|
| 354 | for(vobj_id= vspace[vspace_id].vobj_offset; |
---|
| 355 | vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs); |
---|
| 356 | vobj_id++) |
---|
| 357 | { |
---|
| 358 | if(vobj[vobj_id].type == PTAB) |
---|
| 359 | { |
---|
| 360 | found = 1; |
---|
| 361 | //ptabs allready buided by the boot |
---|
| 362 | _ptabs[vspace_id] = (unsigned int) vobj[vobj_id].paddr; |
---|
| 363 | _puts("ptabs for vspace " ); |
---|
| 364 | _putw(vspace_id); |
---|
| 365 | _puts(" address: ") ; |
---|
| 366 | _putw(_ptabs[vspace_id]); |
---|
| 367 | _puts("\n"); |
---|
| 368 | } |
---|
| 369 | } |
---|
| 370 | |
---|
| 371 | if(!found) |
---|
| 372 | { |
---|
| 373 | _puts("\n[INIT ERROR] Forget to set a PTAB for vspace "); |
---|
| 374 | _putw( vspace_id ); |
---|
| 375 | _puts(" ?\n"); |
---|
| 376 | _exit(); |
---|
| 377 | } |
---|
| 378 | } |
---|
| 379 | |
---|
| 380 | // main loop on the virtual spaces |
---|
| 381 | for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ ) |
---|
| 382 | { |
---|
| 383 | _set_ptpr(vspace_id); |
---|
| 384 | #if INIT_DEBUG_CTX |
---|
| 385 | _puts("\n******* mapping tasks and channels in vspace "); |
---|
| 386 | _puts(vspace[vspace_id].name); |
---|
| 387 | _puts(" ********\n"); |
---|
| 388 | #endif |
---|
| 389 | //initialise all vobjs |
---|
| 390 | for(vobj_id= vspace[vspace_id].vobj_offset; |
---|
| 391 | vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs); |
---|
| 392 | vobj_id++) |
---|
| 393 | { |
---|
| 394 | initialise_vobj(&vobj[vobj_id], vspace_id); |
---|
| 395 | } |
---|
| 396 | |
---|
| 397 | |
---|
| 398 | // Get the physical address of the start_vector for the vspace. |
---|
| 399 | // The start_vector is stored at the beginning of the seg_data segment, |
---|
| 400 | // and contains the start addresses for all tasks defined in a vspace. |
---|
| 401 | // The seg_data segment must be the first vseg defined in |
---|
| 402 | // the mapping_info data structure. |
---|
| 403 | mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset + vspace[vspace_id].funcs_offset]; |
---|
| 404 | #if INIT_DEBUG_CTX |
---|
| 405 | _puts("\n[INIT] : vobj_data name "); |
---|
| 406 | _puts(vobj_data->name); |
---|
| 407 | _puts("\n[INIT] : vobj_data vaddrr "); |
---|
| 408 | _putw(vobj_data->vaddr); |
---|
| 409 | _puts("\n[INIT] : vobj_data addrr "); |
---|
| 410 | _putw(vobj_data->paddr); |
---|
| 411 | #endif |
---|
| 412 | start_vector_base = (unsigned int*)vobj_data->vaddr; |
---|
| 413 | |
---|
| 414 | // map tasks |
---|
| 415 | for ( task_id = vspace[vspace_id].task_offset ; |
---|
| 416 | task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; |
---|
| 417 | task_id++ ) |
---|
| 418 | { |
---|
| 419 | _task_map( task_id, |
---|
| 420 | vspace_id, |
---|
| 421 | base_tty_id, |
---|
| 422 | start_vector_base ); |
---|
| 423 | } |
---|
| 424 | |
---|
| 425 | // increment TTY allocator |
---|
| 426 | base_tty_id = base_tty_id + vspace[vspace_id].ttys; |
---|
| 427 | } |
---|
| 428 | } // end _tc_init() |
---|
| 429 | |
---|
| 430 | //////////////////////////////////////////////////////////////////////////////// |
---|
| 431 | // _peri_init() |
---|
| 432 | // This generic function initializes the interrupt vector, the ICU masks, |
---|
| 433 | // and the timers for the context switch. |
---|
| 434 | // The hardware parameters are NB_CLUSTERS, NB_PROCS, NB_TIMERS, NB_DMAS |
---|
| 435 | // CLUSTER_SPAN, seg_icu_base, seg_timer_base. |
---|
| 436 | // The number of processor per cluster cannot be larger than 8. |
---|
| 437 | // The total number of TTYs cannot be larger than 15. |
---|
| 438 | // The NB_TIMERS, NB_DMAS & NB_PROCS parameters must be equal. |
---|
| 439 | //////////////////////////////////////////////////////////////////////////////// |
---|
| 440 | in_kinit void _peri_init() |
---|
| 441 | { |
---|
| 442 | mapping_header_t* header = (mapping_header_t*)&seg_mapping_base; |
---|
| 443 | mapping_cluster_t* cluster = _get_cluster_base( header ); |
---|
| 444 | |
---|
| 445 | unsigned int cluster_id; |
---|
| 446 | |
---|
| 447 | if ( NB_TIMERS != NB_PROCS ) |
---|
| 448 | { |
---|
| 449 | _puts("\n[INIT ERROR] NB_TIMERS != NB_PROCS\n"); |
---|
| 450 | _exit(); |
---|
| 451 | } |
---|
| 452 | if ( NB_DMAS != NB_PROCS ) |
---|
| 453 | { |
---|
| 454 | _puts("\n[INIT ERROR] NB_DMAS != NB_PROCS\n"); |
---|
| 455 | _exit(); |
---|
| 456 | } |
---|
| 457 | |
---|
| 458 | // interrupt vector initialisation |
---|
| 459 | |
---|
| 460 | _interrupt_vector[0] = &_isr_ioc; |
---|
| 461 | |
---|
| 462 | _interrupt_vector[1] = &_isr_tty_get_0; |
---|
| 463 | _interrupt_vector[2] = &_isr_tty_get_1; |
---|
| 464 | _interrupt_vector[3] = &_isr_tty_get_2; |
---|
| 465 | _interrupt_vector[4] = &_isr_tty_get_3; |
---|
| 466 | _interrupt_vector[5] = &_isr_tty_get_4; |
---|
| 467 | _interrupt_vector[6] = &_isr_tty_get_5; |
---|
| 468 | _interrupt_vector[7] = &_isr_tty_get_6; |
---|
| 469 | _interrupt_vector[8] = &_isr_tty_get_7; |
---|
| 470 | _interrupt_vector[9] = &_isr_tty_get_8; |
---|
| 471 | _interrupt_vector[10] = &_isr_tty_get_9; |
---|
| 472 | _interrupt_vector[11] = &_isr_tty_get_10; |
---|
| 473 | _interrupt_vector[12] = &_isr_tty_get_11; |
---|
| 474 | _interrupt_vector[13] = &_isr_tty_get_12; |
---|
| 475 | _interrupt_vector[14] = &_isr_tty_get_13; |
---|
| 476 | _interrupt_vector[14] = &_isr_tty_get_14; |
---|
| 477 | |
---|
| 478 | |
---|
| 479 | _interrupt_vector[16] = &_isr_switch; |
---|
| 480 | _interrupt_vector[17] = &_isr_dma; |
---|
| 481 | _interrupt_vector[18] = &_isr_switch; |
---|
| 482 | _interrupt_vector[19] = &_isr_dma; |
---|
| 483 | _interrupt_vector[20] = &_isr_switch; |
---|
| 484 | _interrupt_vector[21] = &_isr_dma; |
---|
| 485 | _interrupt_vector[22] = &_isr_switch; |
---|
| 486 | _interrupt_vector[23] = &_isr_dma; |
---|
| 487 | _interrupt_vector[24] = &_isr_switch; |
---|
| 488 | _interrupt_vector[25] = &_isr_dma; |
---|
| 489 | _interrupt_vector[26] = &_isr_switch; |
---|
| 490 | _interrupt_vector[27] = &_isr_dma; |
---|
| 491 | _interrupt_vector[28] = &_isr_switch; |
---|
| 492 | _interrupt_vector[29] = &_isr_dma; |
---|
| 493 | _interrupt_vector[30] = &_isr_switch; |
---|
| 494 | _interrupt_vector[31] = &_isr_dma; |
---|
| 495 | |
---|
| 496 | |
---|
| 497 | // ICU MASKs and TIMERS initialisation |
---|
| 498 | |
---|
| 499 | volatile unsigned int* icu = (unsigned int*)&seg_icu_base; |
---|
| 500 | volatile unsigned int* timer = (unsigned int*)&seg_timer_base; |
---|
| 501 | |
---|
| 502 | for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ ) |
---|
| 503 | { |
---|
| 504 | if ( cluster[cluster_id].procs == 0 ) break; |
---|
| 505 | |
---|
| 506 | icu[ICU_MASK_SET + 0*ICU_SPAN] = 0x000380FF; // ICU_MASK for proc 0 |
---|
| 507 | if ( _scheduler[cluster_id*NB_PROCS + 0].tasks > 1 ) |
---|
| 508 | { |
---|
| 509 | timer[TIMER_PERIOD + 0*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 510 | timer[TIMER_MODE + 0*TIMER_SPAN] = 0x3; |
---|
| 511 | } |
---|
| 512 | |
---|
| 513 | if ( cluster[cluster_id].procs == 1 ) break; |
---|
| 514 | |
---|
| 515 | icu[ICU_MASK_SET + 1*ICU_SPAN] = 0x000C0000; // ICU_MASK for proc 1 |
---|
| 516 | if ( _scheduler[cluster_id*NB_PROCS + 1].tasks > 1 ) |
---|
| 517 | { |
---|
| 518 | timer[TIMER_PERIOD + 1*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 519 | timer[TIMER_MODE + 1*TIMER_SPAN] = 0x3; |
---|
| 520 | } |
---|
| 521 | |
---|
| 522 | if ( cluster[cluster_id].procs == 2 ) break; |
---|
| 523 | |
---|
| 524 | icu[ICU_MASK_SET + 2*ICU_SPAN] = 0x00300000; // ICU_MASK for proc 2 |
---|
| 525 | if ( _scheduler[cluster_id*NB_PROCS + 2].tasks > 1 ) |
---|
| 526 | { |
---|
| 527 | timer[TIMER_PERIOD + 2*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 528 | timer[TIMER_MODE + 2*TIMER_SPAN] = 0x3; |
---|
| 529 | } |
---|
| 530 | |
---|
| 531 | if ( cluster[cluster_id].procs == 3 ) break; |
---|
| 532 | |
---|
| 533 | icu[ICU_MASK_SET + 3*ICU_SPAN] = 0x00C00000; // ICU_MASK for proc 3 |
---|
| 534 | if ( _scheduler[cluster_id*NB_PROCS + 3].tasks > 1 ) |
---|
| 535 | { |
---|
| 536 | timer[TIMER_PERIOD + 3*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 537 | timer[TIMER_MODE + 3*TIMER_SPAN] = 0x3; |
---|
| 538 | } |
---|
| 539 | |
---|
| 540 | if ( cluster[cluster_id].procs == 4 ) break; |
---|
| 541 | icu[ICU_MASK_SET + 4*ICU_SPAN] = 0x03000000; // ICU_MASK for proc 4 |
---|
| 542 | |
---|
| 543 | if ( _scheduler[cluster_id*NB_PROCS + 4].tasks > 1 ) |
---|
| 544 | { |
---|
| 545 | timer[TIMER_PERIOD + 4*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 546 | timer[TIMER_MODE + 4*TIMER_SPAN] = 0x3; |
---|
| 547 | } |
---|
| 548 | |
---|
| 549 | if ( cluster[cluster_id].procs == 5 ) break; |
---|
| 550 | |
---|
| 551 | icu[ICU_MASK_SET + 5*ICU_SPAN] = 0x0C000000; // ICU_MASK for proc 5 |
---|
| 552 | if ( _scheduler[cluster_id*NB_PROCS + 5].tasks > 1 ) |
---|
| 553 | { |
---|
| 554 | timer[TIMER_PERIOD + 5*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 555 | timer[TIMER_MODE + 5*TIMER_SPAN] = 0x3; |
---|
| 556 | } |
---|
| 557 | |
---|
| 558 | if ( cluster[cluster_id].procs == 6 ) break; |
---|
| 559 | |
---|
| 560 | icu[ICU_MASK_SET + 6*ICU_SPAN] = 0x30000000; // ICU_MASK for proc 6 |
---|
| 561 | if ( _scheduler[cluster_id*NB_PROCS + 6].tasks > 1 ) |
---|
| 562 | { |
---|
| 563 | timer[TIMER_PERIOD + 6*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 564 | timer[TIMER_MODE + 6*TIMER_SPAN] = 0x3; |
---|
| 565 | } |
---|
| 566 | |
---|
| 567 | if ( cluster[cluster_id].procs == 7 ) break; |
---|
| 568 | |
---|
| 569 | icu[ICU_MASK_SET + 7*ICU_SPAN] = 0xC0000000; // ICU_MASK for proc 7 |
---|
| 570 | if ( _scheduler[cluster_id*NB_PROCS + 7].tasks > 1 ) |
---|
| 571 | { |
---|
| 572 | timer[TIMER_PERIOD + 7*TIMER_SPAN] = GIET_TICK_VALUE; |
---|
| 573 | timer[TIMER_MODE + 7*TIMER_SPAN] = 0x3; |
---|
| 574 | } |
---|
| 575 | |
---|
| 576 | if ( cluster[cluster_id].procs > 8 ) |
---|
| 577 | { |
---|
| 578 | _puts("\n[INIT ERROR] The number of processors per cluster\n"); |
---|
| 579 | _puts(" cannot be larger than 8\n"); |
---|
| 580 | _exit(); |
---|
| 581 | } |
---|
| 582 | icu = icu + (CLUSTER_SPAN>>2); |
---|
| 583 | timer = timer + (CLUSTER_SPAN>>2); |
---|
| 584 | } |
---|
| 585 | } // end _peri_init() |
---|