CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Dynamic memory - malloc - pic24

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
WS_notLogged
Guest







Dynamic memory - malloc - pic24
PostPosted: Mon Jan 04, 2010 12:50 pm     Reply with quote

Hi.

I have one weird problem.
When I run the code below, on my pic 18F it works without problem.
It has been tested for over 3 weeks.

Now, when I port this code to pic24, program is resetting all the time.
Any idea what can be wrong ?
Code:

  void addData(cap_t g) {
      cap_t *temp1,*temp2;

      if((temp1=(cap_t *)malloc(sizeof(cap_t)))==NULL) {
         printf("\f\nOut of memory");
      }
      else {
         temp1->id=g.id;
         temp1->cap_mode=g.cap_mode;
         strcpy(temp1->dsc,g.dsc);
         temp1->next_cap=NULL;
      }
      if(start_cap==NULL)
         start_cap=temp1;
      else {
         temp2=start_cap;
         while(temp2->next_cap!=NULL) {
            temp2=temp2->next_cap;
         }
         temp2->next_cap=temp1;
      }
     
   }

//***********************************************************

 void loadData() {
      int8 u;
      cap_t kkam;

      for(u=0;u<caps_msg.num_caps;u++) {
         kkam=caps_msg.caps[u];
         addData(kkam);
      }
   }

The program is resetting in full meaning of this word.
It jumps right at the beginning.

W.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Jan 04, 2010 5:00 pm     Reply with quote

As a preliminary remark, I didn't use yet malloc() with PCD and don't know if it's working correctly. Generally,
I think it's of limited use for embedded computing. It can be meaningful however, if the application structure
suggests concurrent usage of part of the RAM. Of course, the respective memory area must be freed before it
can be used for other purposes. But in most cases, static assignment of memory is more effective in my opinion.

Popular candidates for spontaneous processor resets are address error and stack error trap. There has been
already a forum discussion about the too small default PCD stack allocation. It should be better doubled.
Code:
#build(stack = 256)

http://www.ccsinfo.com/forum/viewtopic.php?t=40083

Address errors can be easily produced, either by accesses of non-existing memory or word accesses at
odd addresses. The shown code is incomplete in so far, that the structure definition and (hopefully) preceeding
variable initialization isn't shown. So possible selfmade problems can't be seen. I previously experienced
also address errors caused by PCD compiler bugs, some of these bugs are possibly continuing until most
recent PCD version.

The PIC24 address error trap can be used to reveal coding errors.
http://www.ccsinfo.com/forum/viewtopic.php?t=36479
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Jan 05, 2010 9:02 am     Reply with quote

Quote:
As a preliminary remark, I didn't use yet malloc() with PCD and don't know if it's working correctly.

It doesn't at all. I found that with all PCD versions up to most recent V4.104, the below init code was included at the begin of main, if either
#pragma USE DYNAMIC_MEMORY or #include <stdlibm.h> is specified.

CLR CB9 is an illegal word access to an odd memory location and causes a processor reset.
CLR.B CB9 would be correct.
Code:
0056E:  MOV     #CB8,W4
00570:  MOV     W4,806
00572:  MOV.B   #C5,W0L
00574:  MOV.B   W0L,CB8
00576:  CLR     CB9

P.S.: Why we always find PCD features, that obviously never have been tested after coding?
Guest








PostPosted: Wed Jan 06, 2010 6:01 am     Reply with quote

Hi

Problem is with the assignment of __DYNAMIC_HEAD that is aligned to an odd memory address. Also the position of __DYNAMIC_HEAD is often in the same as that used by locals. I suggest assigning your own and making it a global array. This not only aligns the address but ensures the compiler understands that that memory is not available for other variables.

Remove #USE DYNAMIC_MEMORY

add
Code:

#elif defined(__PCD__)
typedef struct nodet {
   unsigned int16 size;
   unsigned int16 next; }node_t;
#define DMEMSIZE 0x800            // words
  unsigned int16 dynamic_mem[DMEMSIZE];
  unsigned int16 *__DYNAMIC_HEAD;
#endif

#include "memmgmt.c"

void start_dm()
{
   __DYNAMIC_HEAD = dynamic_mem;
   *__DYNAMIC_HEAD = DMEMSIZE*2;
   *(__DYNAMIC_HEAD+1)= 0;
}


and include start_dm(); in your initialisation.
Guest








PostPosted: Wed Jan 06, 2010 6:08 am     Reply with quote

Sorry forgot to say that code should be added to STDLIBM.H
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Jan 06, 2010 8:55 am     Reply with quote

Thank you for the suggestion, it seems to remove at least the obvious errors. Basically it's a PCD bug that
will be hopefully fixed by CCS in time.

I didn't check however the full functionality of malloc(). I also wonder, what's the PCD standard
method to assign dynamic memory? Ideally, it should allocate all free RAM.
Guest








PostPosted: Wed Jan 06, 2010 9:34 am     Reply with quote

Yes it should but there is no heap used by the CCS compiler so it calculates where the locals are. If it was able to calculate the usage of the locals correctly it should work, but as programs get bigger and bigger for large PIC24's the smallest error gets multiplied.

This also stops recursion and pointers to functions that are nice features of ansi C. Of course these functions don't have much use in PIC12/16/18 and in fact accounts for the very efficient code for these small devices, but in the much more powerful PIC24/33's the compiler should have been rewritten to allow full C' features instead of just bolting on to the old compiler design.

This is feel is the main reason that there have been so many bugs in the PCD.

BTW I used dynamic allocation implementing a FAT file system to allow for unknown number of files open at the same time and for path structures for folders to any depth. These PIC24's are sooo good.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Jan 06, 2010 10:33 am     Reply with quote

So you have some hope for the original poster, that malloc is working correctly with the modification?
Guest








PostPosted: Wed Jan 06, 2010 10:58 am     Reply with quote

Yes it did work. I did have some problems with calloc and free that for some reason had to have name changes. I used f_ree and c_alloc. I didn't investigate. The code has been working now for a few weeks and seems to be stable. The application is 24/7 active.
W_Schauberg



Joined: 17 Sep 2009
Posts: 16

View user's profile Send private message

PostPosted: Mon Jan 11, 2010 2:01 am     Reply with quote

Hello FVM and "guest".
I have added the changes to the code and this is the situation:

- I get less error traps ( one or two )
- If I use pointers program generates much more traps
- I can't use some parts of the program
- Program is big but the reduced version makes the same errors.
-------------------------------------------------------------------
@FVM
I will send you new very small version of the code, so when you have time, please take a look.

@guest
Please be so kind and PM me or send me some email, where I can send you test code?. It's quite important to me and I can't describe this part here. The code is small and easy to read...
WS_notLogged
Guest







PostPosted: Thu Jan 14, 2010 5:51 am     Reply with quote

Hi guys.
Any idea regarding my original post ?
I send this problem to ccs support before few days but i still wait for answer.

W.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Jan 14, 2010 4:37 pm     Reply with quote

I finally had some time to look into the code. I found, that only one dataword rather than the full structure is
copied to the function parameter storage
Code:
  kkam=caps_msg.caps[u];
  addData(kkam);

 00732  F8190E     push.w 0x190e
 00734  F91910     pop.w 0x1910
 00736  020654     call 0x000654

Generally, PCD is supporting structures in assignments, kkam is e.g. assigned correctly. Also the parameter
storage for the function is correctly implemented.
Code:
void addData(cap_t g);


Personally, I would never use a construct like this, because it's a huge waste of precious memory. Using a
pointer instead makes the code work correctly, as far as I see.

Code:
  void addData(cap_t *g) {
      cap_t *temp1,*temp2;

      if((temp1=(cap_t *)malloc(sizeof(cap_t)))==NULL) {
         printf("\f\nOut of memory");
      }
      else {
         temp1->id=g->id;
         temp1->cap_mode=g->cap_mode;
         strcpy(temp1->dsc,g->dsc);
         temp1->next_cap=NULL;
      }
      if(start_cap==NULL)
         start_cap=temp1;
      else {
         temp2=start_cap;
         while(temp2->next_cap!=NULL) {
            temp2=temp2->next_cap;
         }
         temp2->next_cap=temp1;
      }
   }

 void loadData() {
      int8 u;
      cap_t *kkam;

      for(u=0;u<caps_msg.num_caps;u++) {
         kkam=&caps_msg.caps[u];
         addData(kkam);
      }
   }


Trying to replace the structure element copy in addData() by a more compact structure assignment reveals
another PCD V4.104 bug.
Code:
*temp1=*g;
 00684  80C895     mov.w 0x1912,0x000a
 00686  80C887     mov.w 0x1910,0x000e
 00688  780086     mov.w 0x000c,0x0002 !!!SHOULD BE 0x000a !!!!
 0068A  780107     mov.w 0x000e,0x0004
 0068C  09001B     repeat #27
 0068E  7858B2     mov.b [0x0004++],[0x0002++]

As many PCD users already experienced, it wants to be spoon-feed and doesn't like complex constructs Sad

Regards,
Frank
miketwo
Guest







Also
PostPosted: Thu Feb 25, 2010 1:12 pm     Reply with quote

I was also having problems of this sort.

In addition to the fix above (removing #USE DYNAMIC MEMORY and coding an alternate), I went to the stddef.h file and changed the definition of size_t, which is used in the malloc code. In mine it was set to int8, and really it should be int16.

Code:
#define size_t unsigned int16


Now I don't get any reboots so long as I'm not trying to allocate more than about 2k... That's pretty good for what I need. Though I wish the malloc function would die more gracefully (just return NULL) if the memory isn't available rather than resetting the processor.

Cheers,
Michael
miketwo
Guest







Even more developments...
PostPosted: Thu Feb 25, 2010 8:13 pm     Reply with quote

Don't want to spam the boards, but have been working on this nonstop, and found a decent workaround.

It basically boiled down to this:
malloc(even number) was ok.
malloc(odd number) caused a reboot.

According to someone who knows this way more than me, this is common knowledge. Embarassed

But I'm a n00b at this, so I'm posting this for the other new guys out there that stumble across this page when they're faced with "random" reboots.

Workaround:

Code:
if(size%2==0) store=(char*)malloc(size);     //even
else store=(char*)malloc(size+1);           //odd
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group