Frame size needed with FAT16_32 and SD card

  • 1
  • 2
  • 3
  • Seite 2 von 3
mc-electronic
Benutzer
Avatar
Geschlecht: keine Angabe
Herkunft: Sauerland NRW
Beiträge: 372
Dabei seit: 03 / 2008
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 24.02.2016 - 09:22 Uhr  ·  #9
Hello bgoolsby,

since you read the correct ADC data via the RS232 even during the "5 minutes failure period" I doubt, that there is a Frame/Stack problem. I can not imagine the program to run correctly (reading ADC and writing RS232) while having Frame problems.

You use blockwrite to write to the SD. What is the Size of your SD, what is the ClusterSize on that SD? (Run CHKDSK on that SD in your PC). How big is the Block you write to the SD? And how big is the file in the moment, when the error begins? (I am looking for something like beginning a new cluster on the SD...)

I use the FAT16_32 a lot for my data logger systems. I also sample data in interrupts. I use blockwrite.. But I do not have any problems. What version of AVRco do you use?

Michael
rh
Administrator
Avatar
Geschlecht:
Herkunft: Germany
Alter: 25
Homepage: e-lab.de
Beiträge: 5558
Dabei seit: 03 / 2002
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 24.02.2016 - 13:29 Uhr  ·  #10
Hello bgoolsby,

I find it suspicious reading SPI in Interrupt and writing the data into a buffer.
This needs a lot of registers. Are you sure that this interrupt service has a
complete register saving for these operations?

rolf
bgoolsby
 
Avatar
 
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 24.02.2016 - 19:33 Uhr  ·  #11
I've tried both FAT16 on 2GB SD cards and FAT32 on 8GB cards, which is what I'm using now. Allocation unit size is 4K. Each blockwrite is also 4K (2048 integer samples). AVRco is 5.07.04.

The interrupt procedure uses PushAllRegs and PopAllRegs as first and last instructions.

I'll go over the .asm file now and report any findings.
Merlin
Administrator
Avatar
Geschlecht:
Alter: 25
Beiträge: 1474
Dabei seit: 03 / 2005
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 25.02.2016 - 17:08 Uhr  ·  #12
How long does it take to fill a buffer?
Avra
Schreiberling
Avatar
Geschlecht:
Herkunft: Belgrade, Serbia
Alter: 54
Homepage: rs.linkedin.com/in…
Beiträge: 653
Dabei seit: 07 / 2002
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 26.02.2016 - 13:51 Uhr  ·  #13
You can monitor stack and frame for all processes.

In initialization execute this once (adapt constants and structures to your liking):
Code
  for i := 1 to NUMBER_OF_PROCESSES do
    Runtime.General.Processes[i].Stack.Valid   := true;
    Runtime.General.Processes[i].Frame.Valid   := true;
    Runtime.General.Processes[i].Stack.MinFree := $FFFF;
    Runtime.General.Processes[i].Frame.MinFree := $FFFF;
  endfor;


Put this proc somewhere:
Code
procedure CheckFrameAndStack;
const
  BAD_RESULT: integer = -1; //$FFFF
var
  i: byte;
begin // Main_Proc, HcpComm and RT_Actions are running processes
  if CheckStackValid(Main_Proc)  = BAD_RESULT then Runtime.General.Processes[IDX_MAIN      ].Stack.Valid := false; endif;
  if CheckStackValid(HcpComm)    = BAD_RESULT then Runtime.General.Processes[IDX_HCP_COMM  ].Stack.Valid := false; endif;
  if CheckStackValid(RT_Actions) = BAD_RESULT then Runtime.General.Processes[IDX_RT_ACTIONS].Stack.Valid := false; endif;

  if CheckFrameValid(Main_Proc)  = BAD_RESULT then Runtime.General.Processes[IDX_MAIN      ].Frame.Valid := false; endif;
  if CheckFrameValid(HcpComm)    = BAD_RESULT then Runtime.General.Processes[IDX_HCP_COMM  ].Frame.Valid := false; endif;
  if CheckFrameValid(RT_Actions) = BAD_RESULT then Runtime.General.Processes[IDX_RT_ACTIONS].Frame.Valid := false; endif;

  for i := 1 to NUMBER_OF_PROCESSES do
    Runtime.General.PowerUp.StackFrameCorrupted := Runtime.General.PowerUp.StackFrameCorrupted or (not Runtime.General.Processes[i].Stack.Valid) or (not Runtime.General.Processes[i].Frame.Valid);
  endfor;

  if Runtime.General.PowerUp.StackFrameCorrupted then // if stack/frame was corrupted at least once since power up
    Buzz(1000); // TODO: in production buzzer should not be heard - save event instead
  endif;
end;


In each process execute something like this:
Code
process HcpComm(120, 280: iData);
begin
  // update local stack and frame consumption statistics:
  Lock(Self);
  if GetStackFree(HcpComm) < Runtime.General.Processes[IDX_HCP_COMM].Stack.MinFree then
    Runtime.General.Processes[IDX_HCP_COMM].Stack.MinFree := GetStackFree(HcpComm);
  endif;
  if GetFrameFree(HcpComm) < Runtime.General.Processes[IDX_HCP_COMM].Frame.MinFree then
    Runtime.General.Processes[IDX_HCP_COMM].Frame.MinFree := GetFrameFree(HcpComm);
  endif;
  Inc(Runtime.General.Processes[IDX_HCP_COMM].ScanCnt);
  UnLock(Self);

 // put your process code here

  Schedule; // not for Main - goto next process (some processes do not need this)
end;

Unfortunately there is nothing like Self in AvrCo, or at least something like GetCurrentProcessID() so you will have to repeat that code with GetStackFree(PROCESS_NAME) and GetFrameFree(PROCESS_NAME) in each process (even Main). Ugly but so far no other way to achieve this. Because of this problem it is not possible to make library for this, but we have to customize code for each project.

Then you add this to your main loop:
Code
    loop // <<< ----------------------- Main RunTime loop ----------------------- >>>
      WatchDogTrig;

      Lock(Self);
      // update global stack and frame corruption diagnostics:
      CheckFrameAndStack;
      // update local stack and frame consumption statistics:
      if GetStackFree(Main_Proc) < Runtime.General.Processes[IDX_MAIN].Stack.MinFree then
        Runtime.General.Processes[IDX_MAIN].Stack.MinFree := GetStackFree(Main_Proc);
      endif;
      if GetFrameFree(Main_Proc) < Runtime.General.Processes[IDX_MAIN].Frame.MinFree then
        Runtime.General.Processes[IDX_MAIN].Frame.MinFree := GetFrameFree(Main_Proc);
      endif;
      Inc(Runtime.General.Processes[IDX_MAIN].ScanCnt);
      UnLock(Self);

      // your code here

    endloop;


When communication requests stack/frame status of each process, you can create resulting strings in a way like this:
Code
  for i := 1 to NUMBER_OF_PROCESSES do
    StackFreeStr  := StackFreeStr  + IntToStr(Runtime.General.Processes[i].Stack.MinFree);
    FrameFreeStr  := FrameFreeStr  + IntToStr(Runtime.General.Processes[i].Frame.MinFree);
    StackValidStr := StackValidStr + HcpBoolToStr(Runtime.General.Processes[i].Stack.Valid);
    FrameValidStr := FrameValidStr + HcpBoolToStr(Runtime.General.Processes[i].Frame.Valid);
    //if i <> NUMBER_OF_PROCESSES then
    //  StackFreeStr  := StackFreeStr  + ',';
    //  FrameFreeStr  := FrameFreeStr  + ',';
    //  StackValidStr := StackValidStr + ',';
    //  FrameValidStr := FrameValidStr + ',';
    //endif;
  endfor;


At the end final communication reply from your AvrCo for command to get stack/frame statistics and other runtime info could be something like this (this example has 7 processes including main):
Zitat
Tick=74
Now=20150317T081938Z
PowerUpMoment=20150317T081824Z
TotalDaysRunning=0.0008565
DeviceID=1
FirstPage=646
LastPage=651
CurrentPagePointer=652
OverwriteOldEvents=1
MinLogLevelFilter=255
StackFrameCorrupted=0
StackValid=1,1,1,1,1,1,1
StackMinFree=89,77,7,21,49,93,32
FrameValid=1,1,1,1,1,1,1
FrameMinFree=108,256,34,45,139,200,31
Sim=0,0,0,0
DI=1,1,1,1,1,1
DO=1,1,1,1,1,1
AI=1,1,1,1,1,1,1,1
AO=1,1,1
MCUCSR=3
ProcessScanCounters=129,4,1539,1539,75,14,1539


It is now very easy to see if you need more or less stack and frame in all your processes.

This is not exact copy/paste and you will need to make your own structures, but you get the idea. Of course, this is an overkill for small projects ;-)
rh
Administrator
Avatar
Geschlecht:
Herkunft: Germany
Alter: 25
Homepage: e-lab.de
Beiträge: 5558
Dabei seit: 03 / 2002
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 26.02.2016 - 14:53 Uhr  ·  #14
Hello Avra,

GetProcessID(self)

is implemented.

rolf
Avra
Schreiberling
Avatar
Geschlecht:
Herkunft: Belgrade, Serbia
Alter: 54
Homepage: rs.linkedin.com/in…
Beiträge: 653
Dabei seit: 07 / 2002
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 26.02.2016 - 16:05 Uhr  ·  #15
Hello Rolf,

Thanks a lot, you are faster then light! B-)

GetStackFree(GetProcessID(self)) - this should work now, right? Can you tell me how do you assign ID to a process? Do you start with 0 for main and then increment by 1 for each process? If so then I could directly access array, which would be great! Is there a way to find out total number of processes in runtime? Something like GetProcessCount()?
bgoolsby
 
Avatar
 
Betreff:

Re: Frame size needed with FAT16_32 and SD card

 · 
Gepostet: 26.02.2016 - 22:02 Uhr  ·  #16
Thanks, Avra, for the debugging ideas.

I didn't see anything amiss in the .asm file. However, yesterday while looking at my corrupted data, I got the idea that the interrupt proc was not always running when it should, leading to dropouts in the data. I took a look at the priority of the interrupt and saw that I had set it to 1. Don't remember why I chose 1. Anyway, I changed it to 3 (highest level) and most of the corruption went away. So I think this was the main, and perhaps only, problem. I think there is not a stack/frame problem.

The data corruption seems to occur for 1-10ms when it happens. I plan to build a monitor program in Labview to record how many interrupt pulses are missed and with this I will have an exact figure.

1. Since I'm running at priority 3, what else has this high priority and could block my procedure?

2. Do the SD card drivers use interrupts or disable them for any period?

p.s. Is there a way I can paste a JPG image into these posts? I'd like to send a picture of the data.
  • 1
  • 2
  • 3
  • Seite 2 von 3
Gewählte Zitate für Mehrfachzitierung:   0

Registrierte in diesem Topic

Aktuell kein registrierter in diesem Bereich

Die Statistik zeigt, wer in den letzten 5 Minuten online war. Erneuerung alle 90 Sekunden.
MySQL Queries: 15 · Cache Hits: 14   129   143 · Page-Gen-Time: 0.040747s · Speichernutzung: 2 MB · GZIP: ein · Viewport: SMXL-HiDPI