#include "OCCAM2C.LNT" #define OCCAM2C_LNT_RESTORE_F /*{{{ File banner*/ /*********************************************************** * Project : GPMIMD ESPRIT P5404 * Authors : Mark Debbage, Mark Hill and Sean Wykes * University of Southampton * * Title : Prototype Source File for generated C * System : Occam 2 C * Filename : Occam2C.c * Version : 1.4 * Date : 1/31/94 **********************************************************/ /*}}} */ /*{{{ Header*/ /****************************************************************************** * File name : Occam2c.c * Owner : OyT * Module Description : SPOC template file * Document name(s) : * Main project name : RIFT/GL-100 (800620UN) * Sub project name : DSP CPU S.W (800821UN) * * Copyright Autronica AS 1996-97 * 7005 TRONDHEIM, NORWAY * * Ver. yy-mm-dd Author Approved Description * ---- -------- ------ -------- ---------------------------------------------- * 0.01 See banner above * 1.24 20Aug98 OyT lint-ed * 1.24 02Dec98 OyT GLKDSP=1044: SETERR involves no lineNo and fileName ******************************************************************************/ /*}}} */ /*{{{ Things removed or added by Teig*/ /* CALL_NAG_F90 USE_SPOC_ISERVER USE_NONBLOCKING_SOCKETS GENPROTO (Inserted again 25.Feb.1997) LIBRARY_UNIT (Inserted again 25.Feb.1997) signal.h sys/time.h USESIGTIMER NO_INT64 NO_REAL64 OCCAM_MAIN __GNUC__ main(void) instead of main(....) DEFAULT_MEMSIZE_IN_INTS removed << PARAMETERS >> field removed SocketEvent: // static int SocketEvent = false; // while(CURTASK != NoTask || TimerEvent || SocketEvent) SHOWTASKING test, it was not defined TIMER is not zeroed at power-up "#ifndef NO_DEBUG" annd all code within have been removed For analysis of system behaviour in emulator: idle_ms, idle_max_ms, timer_int_tick added Reset_idle_max_ms added survivalFromLastRun added "DINT1" DMA1 interrupt handled (17Apr98) PC-lint done (Aug98) */ /*}}} */ /*{{{ Insert SWITCHES*/ <<SWITCHES>> // occ2c SoftwDes.occ -mn -d // Here are these switches, clipped from a generated C-file: // #define BYTES_PER_WORD 4 // #define TERMINATE_ON_ERROR // #define CHECK_CONVERSIONS // #define CHECK_ARRAYS // #define CHECK_RANGES // #define NO_DEBUG // #define FASTGOTOS // #define SOURCE LITTLE // To remove lint e750 "local macro not referenced": #ifdef BYTES_PER_WORD #endif #ifdef TERMINATE_ON_ERROR #endif #ifdef CHECK_CONVERSIONS #endif #ifdef CHECK_ARRAYS #endif #ifdef CHECK_RANGES #endif #ifdef NO_DEBUG #endif #ifdef FASTGOTOS #endif #ifdef SOURCE #endif /*}}} */ /*{{{ defines*/ #define BITS_PER_WORD (BYTES_PER_WORD * 8) // 32 Teig #define FAST_SHIFTS // To avoid side-effect warning 666 from PC-lint // #define DEBUG_COUNT_PROCESS_SCHEDULES // Teig /*}}} */ /*{{{ includes*/ #ifdef GENPROTO // makedep doesn't understand the ifdef! // #include <stdio.h> #endif #include "Occam2C.h" #include "C_RefOcc.inc" // Teig /*}}} */ /*{{{ Insert data struct tree*/ /*lint -save -e793 ANSI limit of 127 'structure members' exceeded processing is unaffected */ /*lint ++flb Force it to be considereded as a library, so that "local structure member not referenced" (754) is suppressed during module wrap-up */ <<HEADER>> // /*lint --flb */ /*lint -restore */ /*}}} */ /*{{{ statics*/ #if (defined GENPROTO) || !(defined LIBRARY_UNIT) /*{{{ statics for GLK-100*/ jmp_buf STOPP_env; tTask *QFP[NUM_PRIORITY_LEVELS]; tTask *QBP[NUM_PRIORITY_LEVELS]; tTask *CURTASK; tTask *QTM; tTimer TIMER; static int TimerEvent = false; // DMA Interrupt 1 at interrupt vector EA+012 handling: static tTask *DINT1TASK = NoTask; // Teig static int DINT1Event = false; // Teig static CHAN *DINT1EventChannel; // Teig Same name in "O_RawDri.inc" // The Texas emulator won't see these values if we don't initialize them: static int idle_ms = 0; // Teig static int idle_max_ms = 0; // Teig static int timer_int_tick = false; // Teig static int survivalFromLastRun = 0; // Teig #define NUM_BREAKPOINT (27 + 1) // 1 extra for "default" // Teig static int breakpointCnt[NUM_BREAKPOINT] = {0}; // Teig #define DUAL_PORT_SURVIVAL_TO_LON (int *) 0x810080 // 0x8080 on Lon (See "DualPort.c") // Pointer to a single byte in dual-port, situated in righmost byte of int32: static int *survivalToDualPort_ptr = DUAL_PORT_SURVIVAL_TO_LON; // Nice for debugger, and we don't have to "read,bitor,write" with dual-port, only "write": static int survivalToDualPort_copy = 0; #define TOP_OF_STACK_TST_VALUE (int)0xf0e1d2c3 // Something unique! static int *topOfStackPtr = 0; static int schedCnt = 0; // ifdef DEBUG_COUNT_PROCESS_SCHEDULES /*}}} */ #endif #ifdef GENPROTO /*{{{ seterr*/ void seterr(char *M,int L,char *F) {} /*}}} */ /*{{{ struct Prototypes*/ struct Prototypes { char *Proto; char *Define; int Space; }; /*}}} */ /*{{{ static struct Prototypes Table[] =*/ static struct Prototypes Table[] = { <<PROTOTYPES>> {NULL,NULL,0} } ; /*}}} */ /*{{{ int main(int argc, char**argv)*/ int main(int argc, char**argv) { char *name; FILE *f; int fcnt; CheckPrimitiveSizes(); if (argc<2) { name="<<NAME>>.hdr"; f=fopen(name,"w"); } else { name = argv[argc-1]; if (name[0]=='-') { name = "stdout"; f=stdout; } else { f=fopen(name,"w"); } } fcnt=argc-1; if (f==NULL) { fprintf(stderr,"Fatal - could not open file %s\n",name);exit(-1); } else { int arg; int i; fprintf(f,"#ifndef __<<NAME>>_INCLUDES__\n"); fprintf(f,"#define __<<NAME>>_INCLUDES__\n"); for(arg = 1; arg < fcnt; ++arg) { FILE *fh = fopen(argv[arg],"r"); if (fh == NULL) { fprintf(stderr,"Fatal - could not read file %s\n",name); exit(-1); } while(!feof(fh)) { char line[256]; if (fgets(line,256,fh) == NULL) break; if (line[0] == '#') if (strncmp(line,"#define WS",10)!=0) continue; fputs(line,f); } fclose(fh); } i = 0; while (Table[i].Proto!=NULL) { if (Table[i].Define != NULL) { fprintf(f,"typedef struct SF_%s tSF_%s;\n",Table[i].Define,Table[i].Define); fprintf(f,"#define WS_%s (%d)\n",Table[i].Define,Table[i].Space); } fprintf(f,"%s\n",Table[i].Proto); i++; } fprintf(f,"#endif\n"); if (f!=stdout) fclose(f); } return(0); } /*}}} */ #endif /*}}} */ #ifndef LIBRARY_UNIT /*{{{ Reset_idle_max_ms*/ static int Reset_idle_max_ms (void) { int old; { old = idle_max_ms; idle_max_ms = 0; return (old); } } /*}}} */ /*{{{ Set_survivalFromLastRun, Get_survivalFromLastRun*/ int Get_survivalFromLastRun (void) { return (survivalFromLastRun); } void Set_survivalFromLastRun (const int SurvivalFromLastRun) { survivalFromLastRun = SurvivalFromLastRun; } /*}}} */ /*{{{ Set_survivalToDualPort, Set_survivalToDualPort_AndCopy*/ // Dual-port access without hardware semaphore Ping-Pong // is acceptable under the following conditions: // // 1. No read/read conflict // We don't have any read/read situation at all // 2. No write/read conflict // DSP writes when it wants to. The address is exclusive. // Lon-controller reads in the phase when it is holding DSP reset. // -> No conflict void Set_survivalToDualPort (const int SurvivalToDualPort) { // This procedure is used during a controlled shutdown // Right-most byte only: // We "bitor" with a copy instead of "read,bitor,write" // Dual-port access without hardware semaphore Ping-Pong: *survivalToDualPort_ptr = SurvivalToDualPort | survivalToDualPort_copy; } void Set_survivalToDualPort_AndCopy (const int SurvivalToDualPort_copy) { // This procedure is used to leave _something_ in case of a _missing_ controlled shutdown, // followed by a reset initiated by the Lon-controller // Right-most byte only: // Dual-port access without hardware semaphore Ping-Pong: *survivalToDualPort_ptr = SurvivalToDualPort_copy; survivalToDualPort_copy = SurvivalToDualPort_copy; } /*}}} */ /*{{{ c_int09 Timer interrupt*/ /* * OBSERVE: For linker to find the timer interrupt, name c_int09 MUST be used! */ // Texas wants us to do it wihout "extern", but this costs us // lint filters (714 = not referenced) and (765 = could be made static) // See "options.lnt", // // extern void // c_int09 (void); void c_int09 (void) // If static, the linker will not see it! { // This timer interrupt routine takes som 92-100 clock ticks. // With 1 ms (20 000 clock ticks) this is an overhead of some 0.5% TIMER = TIMER + 1; timer_int_tick = true; // Also used at power-up! if (QTM != NoTask && AFTER(TIMER,QTM->comms.timer.time)) { TimerEvent = true; } } /*}}} */ /*{{{ c_int12_signal_if - From DMA channel 1 interrupt*/ /* * Called from "Ser_Port.c" * Exported in "DINT1.h" */ void c_int12_signal_if (void) { if (DINT1TASK != NoTask) { DINT1Event = true; } } /*}}} */ /*{{{ BlinkAndLeaveOn*/ void BlinkAndLeaveOn (const int NoOfBlinks) { int blinks; for (blinks = 0; blinks < NoOfBlinks; blinks++) { #define OneSecond 714000 int cnt = 0; Write_DSP_LEDs (0x00); for (cnt = 0; cnt < OneSecond; cnt++) {} Write_DSP_LEDs (0x11); for (cnt = 0; cnt < OneSecond; cnt++) {} } } /*}}} */ /*{{{ LON_Synch_Breakpoint etc.*/ // // // 1. Now press the GLK-100 push-button to reset // LON-controller. // 2. Stare at the "SystemError" LED, and hit "F5" // when it goes off! // PRECONDITION: // Both connections from reset-logic and Lon-controller // to DSP reset-pin must be broken! void LON_Synch_Breakpoint (void) { } // // // 1. You did not hit "F5" accurately enough // 2. The LON-controller isn't working properly // 3. The PRECONDITION above hasn't been met // TRY: // Restart emulator and LON-controller again and // be more accurate (count to 4.5)! void LON_Synch_Error_TryAgain (void) { } /*}}} */ /*{{{ Breakpoint*/ static void InitBreakpointCnt (void) { int i; for (i=0; i < NUM_BREAKPOINT; i++) { breakpointCnt[i] = 0; } i = breakpointCnt[0]; // For lint, to avoid e551 on breakpointCnt } // // // Be sure to set a breakpoint at BPException below! // void Breakpoint (const int BreakpointNo) { switch (BreakpointNo) { case 0: breakpointCnt[0]++; break; // BpException case 1: breakpointCnt[1]++; break; // BpViewLastException case 2: breakpointCnt[2]++; break; // BpAny case 3: breakpointCnt[3]++; break; // BpSpecial case 4: breakpointCnt[4]++; break; // BpCMain case 5: breakpointCnt[5]++; break; // BpOccamTopLevel case 6: breakpointCnt[6]++; break; // BpDualPortDriver case 7: breakpointCnt[7]++; break; // BpDualPortComIn case 8: breakpointCnt[8]++; break; // BpDualPortComOut case 9: breakpointCnt[9]++; break; // BpDualPortEventIn case 10: breakpointCnt[10]++; break; // BpDualPortEventOut case 11: breakpointCnt[11]++; break; // BpInMergePackets case 12: breakpointCnt[12]++; break; // BpOutSplitToPackets case 13: breakpointCnt[13]++; break; // BpClientLogOn case 14: breakpointCnt[14]++; break; // BpMessageRouter case 15: breakpointCnt[15]++; break; // BpAlbumMonitor case 16: breakpointCnt[16]++; break; // BpCurveServer case 17: breakpointCnt[17]++; break; // BpFileServer case 18: breakpointCnt[18]++; break; // BpFileServerCmdInt case 19: breakpointCnt[19]++; break; // BpFlashDriver case 20: breakpointCnt[20]++; break; // BpAlarmServer case 21: breakpointCnt[21]++; break; // BpVolumeServer case 22: breakpointCnt[22]++; break; // BpUllCalc case 23: breakpointCnt[23]++; break; // BpRawDriver case 24: breakpointCnt[24]++; break; // BpEventRouter case 25: breakpointCnt[25]++; break; // BpCodeChecksum case 26: breakpointCnt[26]++; break; // BpAlbumErr default: breakpointCnt[27]++; SETERR (MSG_CASE); } } // // // // // // // // // // // // /*}}} */ /*{{{ Error handling*/ ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// static void DONE_SETERR (void) {} void seterr (char *Message, int LineNo, char *FileName) { int firstChar = (int) Message[0]; Set_survivalToDualPort (firstChar); Breakpoint(0); BlinkAndLeaveOn(60); SETERR_PROCEED; } /*lint !e715 FileName, LineNo (line _) not referenced */ ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // GLKDSP=1044: seterr_ is new void seterr_ (char *Message) { seterr (Message,__LINE__,__FILE__); // Always h e r e } ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// /*}}} */ /*{{{ Init_Timer*/ static void Init_Timer (void) { // TIMER = 0; // Teig: If we don't initialize it, we get random start-times! QTM = NoTask; TimerEvent = false; } /*}}} */ /*{{{ Set_DINT1EventChannel*/ static void Set_DINT1EventChannel (CHAN *chan) { DINT1EventChannel = chan; DINT1TASK = CURTASK; } /*}}} */ /*{{{ Init_Scheduler*/ static void Init_Scheduler (void) { int i; for(i = 0; i < NUM_PRIORITY_LEVELS; ++i) QFP[i] = (QBP[i] = NoTask); CURTASK = NoTask; Init_Timer(); } /*}}} */ /*{{{ Scheduler*/ static void Scheduler (void) { if (setjmp(STOPP_env)) { DeSchedule((tTaskMode) 0); } while(CURTASK != NoTask || TimerEvent || DINT1Event) { int pri; /*{{{ if (DINT1Event)*/ if (DINT1Event) { int data = 1; if (ChanOut4_InterruptEvent (DINT1EventChannel, &data, DINT1TASK) == 1) { DINT1Event = false; // If, for some reason ChanOut4_InterruptEvent fails to find a receiving task, // let's just continue until it finds one. We do this by keeping DINT1Event true. // This is perfectly sound, the receiving task may be processing some other // request, or may have this guard disabled. } else { DINT1Event = true; // Just so that we have something to stop on in the debugger } } /*}}} */ /*{{{ if (TimerEvent)*/ // No "else if" here! We want to accept timeouts even if DINT1Event hasn't been cleared! if (TimerEvent) { TimerEvent = false; while(QTM != NoTask && AFTER(TIMER,QTM->comms.timer.time)) { if (QTM->AltMode == Waiting_p) QTM->AltMode = TReady_p; ReSchedule(QTM); } } /*}}} */ for (pri = 0; pri < NUM_PRIORITY_LEVELS; ++pri) { if ((CURTASK=QFP[pri]) != NoTask) // Assignemt of CURTASK is here! { // lint 534: Ignoring return value of // lint 746: call to unidentified function not made in the presence of a prototype // Next task is scheduled through this point CURTASK->Func (CURTASK->FP); /*lint !e534 !e746 See above */ #ifdef DEBUG_COUNT_PROCESS_SCHEDULES schedCnt++; #endif if (*topOfStackPtr != TOP_OF_STACK_TST_VALUE) { SETERR(MSG_STACK_OVERFLOW); } break; } } /*{{{ Idle*/ if (CURTASK == NoTask && QTM != NoTask) { idle_ms = 0; while((TimerEvent==0) && (DINT1Event==0)) { // Teig // Observe that timer interrupt latency is // increased a little with this code: Set_survivalToDualPort(1); if (timer_int_tick == true) { idle_ms++; timer_int_tick = false; if (idle_ms > idle_max_ms) { idle_max_ms = idle_ms; } } } } /*}}} */ } SETERR(MSG_TA); /* Teig */ } /*}}} */ /*{{{ Start_Process*/ void Start_Process(register tTask *task, register tFuncPtr Func, register void *FP, register char *name,int Priority) { static int NextTaskId = 0; task->FP = FP; task->Func = Func; task->state = EXEC_p; task->name = name; task->Parent = CURTASK; task->Children = 0; task->Next = NoTask; task->AltMode = NotAlting_p; task->TaskId = NextTaskId++; // (INT) decoration to avoid lint -e641 Converting enum to int task->TaskPriority = (CURTASK != NoTask && CURTASK->TaskPriority == (INT)HighPriority) ? (INT)HighPriority : Priority; ((tHeader *)FP)->ProcName = name; if (Priority < 0 || Priority >= NUM_PRIORITY_LEVELS) SETERR(MSG_PRI); if (QFP[task->TaskPriority]) QBP[task->TaskPriority]->Next = task; else QFP[task->TaskPriority] = task; QBP[task->TaskPriority] = task; if (CURTASK != NoTask) CURTASK->Children++; else CURTASK = task; } /*}}} */ /*{{{ int main (void)*/ // // // 1. Now press "F5" and wait 5 seconds for LON synch. point. int main (void) { void *FP = NULL; tTask main_t; const uint32_a NoOfInt32s = sizeof(tSF_<<MAIN>>); uint32_a missing; unsigned int stackStart, stackSize; bool_a ramTstErr; int testTimerNow; { tSF_<<MAIN>> *MAINFP=(tSF_<<MAIN>> *)Malloc32(NoOfInt32s, &missing); // -------------------------------------------------------------------- // File "occam2c.lnt" must be used, else lint will complain: // We must use it for an already existing value: testTimerNow = OCCAM2C_LNT_USED_AVOID_e766_F; // -------------------------------------------------------------------- // Problems with "restart" in debugger and timer: testTimerNow = 1; // Set it to zero instead if you want to avoid Timer test Seterr // -------------------------------------------------------------------- /*{{{ External ram test*/ if (RamTstUsage_ms() == TRUE) /*lint !e641 Converting enum to int */ { // Don't do it if running in emulator! ramTstErr = FALSE; // OK until otherwise proven ramTstErr = X0_RamTstErr (ramTstErr); ramTstErr = X1_RamTstErr (ramTstErr); ramTstErr = Y_RamTstErr (ramTstErr); if (ramTstErr == TRUE) { // was s e t e r r (MSG_EXRAM_ERR,__LINE__,__FILE__); SETERR (MSG_EXRAM_ERR); } } /*}}} */ /*{{{ Initialize stack test value*/ stackStart = Get_StackStart(); stackSize = Get_StackSize(); // Referenced to SP in c_int00 // Margin 0x100 // + In main (here) stack has grown since c_int00 by 0x01c // - Growth of stack in Get_StackStart is 0x002 // ------------------------------------------------------- // = SubtractBy 0x11a // ======================================================= stackSize = stackSize - 0x11a; topOfStackPtr = (int *)(stackStart + stackSize); *topOfStackPtr = TOP_OF_STACK_TST_VALUE; /*}}} */ Set_survivalToDualPort_AndCopy(0); InitBreakpointCnt(); InitBusStrobes(); // In "cpureg.c" /*{{{ malloc error handling*/ if (MAINFP==NULL) { // was s e t e r r (MSG_MALLOC,__LINE__,__FILE__); SETERR (MSG_MALLOC); /* fprintf(stderr,"Error - Malloc of %s bytes for occam workspace failed\n",sizeof(tSF_<<MAIN>>)); */ } /*}}} */ CheckPrimitiveSizes(); // In occam2c.h /*{{{ Start and check timer interrupt*/ { if (CodeIsRunningInRam() == 1) // In "RamTst.c" { // We need to do this for programs booted to external RAM via booting mechanism: ReallocateVectors(); // In "cpureg.c" } } { int cnt; const INT OccamHighAndLowPriTime_1000uS = 1000; // 1mS InitTimer0Int(OccamHighAndLowPriTime_1000uS); // In "cpureg.c" if (testTimerNow == 1) { /*{{{ Test timer*/ //--------------------------------------------------------------------------- #define o0 // o2 or o0 // // #ifdef o2 // Rather: non-specified "o"-option, is it "o2"? // #define cnt1 400 // #define cnt2 171 // #endif // // #ifdef o0 // #define cnt1 800 // #define cnt2 500 // #endif // // // Question to you: is optimalization in debug and flash versions alike? // // They must be! (See m_gl100.mak) // // // Unspecified compiler optimalization level (=o2?) ******** // // Compiler optimalization level (=o0) ******** // // ---------- Accumulated time: -------------------- 0 us // for (cnt = 0; cnt < cnt1; cnt++) {} // ------------- // // ---------- Accumulated time: -------------------- 767 us // if (timer_int_tick != false) // { // // Observe that compiler optimalization level will // // affect this measurement! // // was s e t e r r (MSG_TIMER,__LINE__,__FILE__); // SETERR (MSG_TIMER); // Too fast! // // Set testTimerNow to 0 first in "main" if you want to avoid it! // } // // ---------- Accumulated time: -------------------- 768 us // for (cnt = 0; cnt < cnt2; cnt++) {} // -------------- // // ---------- Accumulated time: -------------------- 1100 ms 1080 ms // if (timer_int_tick == false) // { // // Observe that compiler optimalization level will // // affect this measurement! // // was s e t e r r (MSG_TIMER,__LINE__,__FILE__); // SETERR (MSG_TIMER); // Too slow! // // Set testTimerNow to 0 first in "main" if you want to avoid it! // } // //-------------------------------------------------------------------------- /*}}} */ } } /*}}} */ Init_Scheduler(); STARTP(&main_t,<<MAIN>>,MAINFP,"<<MAIN>>",(INT)LowPriority); Scheduler(); return 0; } } /*}}} */ #endif #ifndef GENPROTO /*{{{ Insert DEBUG*/ <<DEBUG>> /*}}} */ /*{{{ Insert CODE*/ <<CODE>> /*}}} */ #endif #include "OCCAM2C.LNT" // To catch restore's