Frame size needed with FAT16_32 and SD card

  • 1
  • 2
  • 3
  • Page 2 of 3
mc-electronic
Benutzer
Avatar
Gender: n/a
Location: Sauerland NRW
Posts: 372
Registered: 03 / 2008
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 24.02.2016 - 09:22  ·  #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
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 24.02.2016 - 13:29  ·  #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
 
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 24.02.2016 - 19:33  ·  #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
Gender:
Age: 24
Posts: 1409
Registered: 03 / 2005
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 25.02.2016 - 17:08  ·  #12
How long does it take to fill a buffer?
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 26.02.2016 - 13:51  ·  #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):
Quote
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
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 26.02.2016 - 14:53  ·  #14
Hello Avra,

GetProcessID(self)

is implemented.

rolf
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 26.02.2016 - 16:05  ·  #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
 
Subject:

Re: Frame size needed with FAT16_32 and SD card

 · 
Posted: 26.02.2016 - 22:02  ·  #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
  • Page 2 of 3
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   129   143 · Page-Gen-Time: 0.049347s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI