This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

problem with large buffers in ram

Hi,
MCU: LPC2138
I am writing a code that takes data from serial port (interrupt driven) and stores it in queues.
Here's an overview:

//////////////
struct queue{
   char *buffer;
   int wp;
   in rp;
 };

char buffer1[6000];
char buffer2[1000];
char buffer3[600];
char uartBuffer[100];
struct queue myQueue;

void initQueue(char* bufferQueue, int size) {
    myQueue.buffer = bufferQueue;
    myQueue.wp = 0;
    myQueue.rp = 0;
}

void enqueue(char *data) {
  q = &myQueues;
  while(data[i] != '\0') {
        q->buffer[q->writePointer++] = data[i++];
        if (q->writePointer >= q->size)
                q->writePointer = 0;
        }
        q->buffer[q->writePointer++] = 0;
        if (q->writePointer >= q->size)
                q->writePointer = 0;
}

int main () {
  char str[50];
  UART0_init(9600);
  UART0_interrupt_init();
  initQueue(buffer3, 600);

  while(1) {
     sprintf(str, "wp: %d    rp: %d", myQueues.wp, myQueues.rp);
     UART0_sendstring(str);
  }
}

void UART0Isr() {
     UARTbuffer[i] = UART0_getbyte(); // get data until sequence completed
     if(/*sequence complete condition*/)
           enqueue(UARTbuffer);
}

Now, the problem is that the controller hangs after "enqueuing" 8 sequences(all sequences are same). and the number 8 decreases if i increase the size of sequence.

if i reduce the buffer3 size to 500 or less, code works perfectly fine.
for buffer3 size >= 500 ----> code hangs

if i interchange the declaration sequence of global variables like:

char buffer3[600];
char buffer1[6000];
char buffer2[1000];

it gets ok. Atleast for 1000 sequences.

if i disable all interrupts and use enqueue in main in a while loop, its runs fine.

void main() {
while(1) {
  enqueue(sequence);    //works fine here
}
}

Thanks for reading and advance thanks for helpful replies.

Regards,
Salman.

Parents
  • I have even done this manually:

    unsigned char vectors[64] __attribute__((at(0x40000000)));// reserve space for IRQ vectors
    void copy_vectors (void) {
            memcpy (vectors, 0, 64); // copy original IRQ vectors to RAM
            MEMMAP = 2; // fetch vectors from RAM
    }
    
    
    int main() {
         copy_vectors();
    
         //other code
    }
    

    But this too does not solve the problem.

    Now one strange thing is that if remove the bootloader and set the Application code to start in rom from 0x000 and ram from 0x40000000 ..........the problem disappears.

Reply
  • I have even done this manually:

    unsigned char vectors[64] __attribute__((at(0x40000000)));// reserve space for IRQ vectors
    void copy_vectors (void) {
            memcpy (vectors, 0, 64); // copy original IRQ vectors to RAM
            MEMMAP = 2; // fetch vectors from RAM
    }
    
    
    int main() {
         copy_vectors();
    
         //other code
    }
    

    But this too does not solve the problem.

    Now one strange thing is that if remove the bootloader and set the Application code to start in rom from 0x000 and ram from 0x40000000 ..........the problem disappears.

Children
  • Maybe see this: (Not for LPC21xx, but for LPC23xx)

    http://www.keil.com/forum/13106/
    Moshe Tal, 10-Sep-2008 17:18 GMT
    --------------------------------
    Additionally, you have to change memory area for application in Options for Target -> Target -> Read\Write memory area to start from 0x40000100 and contain only 0x7F00 (possible lower, but this for safty).
    So, the application will leave the vectors table RAM untouchable.

    http://www.keil.com/forum/13707/
    Predrag Despotovic, 13-Dec-2008 12:07 GMT
    -----------------------------------------
    IRAM1 start:0x40001000 size:0x7000
    (I was playing with bootloader IRAM1_size. And in my case, bootloader needs somewhere around 0xDFF of RAM. So in order not to overlap it's area, my IRAM1 starts at 0x40001000. Moshe Tal suggested 0x40000100 for his lpc2368 - not enough in my case. Try playing with IRAM1_size in bootloader project to determine your minimum...)

  • Well, Previously i was using IROM:0x1000 SIZE:0x80000 and IRAM1:0x40000040 SIZE:0x8000 and these are the settings recommended in the NXP's Application Note AN10853 (LPC2000 secondary bootloader for code update using IAP) page 11.

    Now as recommended by you i changed it to IRAM1:0x40001000 SIZE:0x7000, and the code is working fine. Thanks for help.

    Regards,
    Salman.

  • Note that NXP recommendations can't take into account any Keil startup files that performs a memory copy of a vector table into RAM and how that copying could result in an overwrite of other information in case the application have stored something important to the overwritten address range.

    It's always important to understand what is happening in a system, which was the reason I did recommend you to first spend time with the processor user manual (to understand the functionality of the processor and the needs) before looking at the Keil startup file.

  • Hi, In this post:http://www.keil.com/forum/13707/ Predrag Despotovic said that :
    "(I was playing with bootloader IRAM1_size. And in my case, bootloader needs somewhere around 0xDFF of RAM. So in order not to overlap it's area, my IRAM1 starts at 0x40001000. Moshe Tal suggested 0x40000100 for his lpc2368 - not enough in my case. Try playing with IRAM1_size in bootloader project to determine your minimum...)"

    Now my question is why is it necessary to not to overlap the RAM area of bootloader in application code. ? Don't we only need to protect the 64 bytes of exception vectors of RAM area.
    Wouldn't rest of the ram be available to be used by application code.

  • Now my question is why is it necessary to not to overlap the RAM area of bootloader in application code. ?

    It is not necessary. I suppose that in your usage of "protect" you actually mean "not set to 0" upon application startup code execution.

  • I miss read your previous post. The bootloader and application can share RAM - because the bootloader should never run after the startup process. Note that you could have intermittent software layer between the application and bootloader that _can_ run alongside the application and do require RAM - be careful there.

  • Yeah i mean to protect by setting application code IRAM1 start address at 0x40 or ox50 for safety lets say. Just enough not to overlap the first 64 bytes of ram.

    Other then that changing the iram1 to 0x100 or 0x1000 does not makes sense.

  • The bootloader and application can share RAM
    Ok.

    But that would be very clear and visible if there is any such software layer.
    Lets say i am using the default SD/MMC bootloader provided by nxp for LPC2100 series.

    In that case what i apprehended is right?

  • Hi Salman Liaquat,

    UM10211
    Chapter 29: LPC23XX Flash memory programming firmware

    3.2.8 RAM used by ISP command handler
    ISP commands use on-chip RAM from 0x4000 0120 to 0x4000 01FF. The user could use
    this area, but the contents may be lost upon reset. Flash programming commands use the
    top 32 bytes of on-chip RAM. The stack is located at RAM top - 32. The maximum stack
    usage is 256 bytes and it grows downwards.

  • UM10114
    Chapter 21: LPC21xx/22xx Flash memory controller

    5.11 RAM used by ISP command handler
    ISP commands use on-chip RAM from 0x4000 0120 to 0x4000 01FF. The user could use
    this area, but the contents may be lost upon reset. Flash programming commands use the
    top 32 bytes of on-chip RAM. The stack is located at RAM top - 32. The maximum stack
    usage is 256 bytes and it grows downwards.

  • In my case, 0x40000200 is good enough.

    http://www.keil.com/forum/13707/

    John Linq, 8-Apr-2009 10:27 GMT

    2. Set IRAM1 Start: 0x40000200 Size: 0x7E00

  • I have no longer worked on the ARM platform for quite a long time.
    I can not remember correctly that why I reserve 200 bytes.
    But I do remember that I had found some reasons/explanations before, just fail to recall them.
    I believe the reason is related to 1st and 2nd bootloaders, ISP/IAP needs.

  • GNU tool-chain linker script

    ieee.ucsd.edu/.../LPC2148-ROM.ld

    /*   RAM used by boot loader:  0x40000120 - 0x400001FF  (223 bytes) for ISP variables                     */
    /*                             0x40007FE0 - 0x4000FFFF  (32 bytes)  for ISP and IAP variables             */
    /*                             0x40007EE0 - 0x40007FE0  (256 bytes) stack for ISP and IAP                 */
    

    mbed.org/.../LPC1768.ld

    MEMORY
    {
      rom (rx)  : ORIGIN = 0x00000000, LENGTH = 512K
    
      ram (rwx) : ORIGIN = 0x100000C8, LENGTH = 0x7F38
    
      ram1(rwx) : ORIGIN = 0x2007C000, LENGTH = 16K
      ram2(rwx) : ORIGIN = 0x20080000, LENGTH = 16K
    }