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

Memcpy

Hello,

I am new to embedded programming, particularly C, and I am trying to write bytes to code memory, within my already executing code. The purpose is to see if I can write a program to program memory within a program. I believe that is sometimes called a boot loader.

Here is what I have: (It's a simple approach)

#include "REG51XC2.h"
#include <string.h>


unsigned char code code_buffer [16] _at_ 0x0B00;
unsigned char byte = 0x11;
unsigned char * bytep = &byte;

void main(void)
{
        memcpy(code_buffer, bytep, sizeof(code_buffer));
        while(1);
}

What I am trying to do is assign some space in program memory (location 0x0B00) and write a byte there using the method "memcpy".

When I run my emulation, I can see in the disassembler that no where does it use the command "MOVC" which I know to be the assembly way of writing to code memory.

     9: void main(void)
    10: {
    11:         memcpy(code_buffer, bytep, sizeof(code_buffer));
C:0x0982    7800     MOV      R0,#0x00
C:0x0984    7C0B     MOV      R4,#byte(0x0B)
C:0x0986    7DFF     MOV      R5,#0xFF
C:0x0988    AB08     MOV      R3,bytep(0x08)
C:0x098A    AA09     MOV      R2,0x09
C:0x098C    A90A     MOV      R1,0x0A
C:0x098E    7E00     MOV      R6,#0x00
C:0x0990    7F10     MOV      R7,#0x10
C:0x0992    1208D0   LCALL    C?COPY(C:08D0)
    12:         while(1);

The one good thing, though, is that the assignment of "code_buffer" was successful in putting placing it at 0x0B00.

C:0x0AFF    00       NOP
                 code_buffer:
C:0x0B00    00       NOP
C:0x0B01    00       NOP
C:0x0B02    00       NOP

So what my understanding is, is memcpy will allow me to copy values to data memory (internal or external) but not program memory.

With this in mind, does that mean I will be writing a version of the "memcpy" function in assembly to get the data into program memory, or is there another function in C I could use? If so, is there any material I can reference or some code I could use to implement the function above?

I appreciate any help,

Max

  • A normal 8051 processor is physically unable to write to code memory. There is zero instructions that can do that, so there is zero way you can write a program that can manage this.

    You may be able to find specific 8051 chips that can perform in-application-programming. But not by writing to code memory. They may have methods where specific XDATA memory might overlay code memory. Or they may have methods to write to magic processor registers that will work as a magic window into the code flash. There could exist 8051 cores that have some extra instructions added to the instruction set - but then assemblers/compilers will not be able to produce such code since they would not know about this extension.

    But no normal memcopy() etc can do what you want, since the processor instruction set was never intended to manage what you want. And only the specific documentation for your specific 8051 variant might tell if there are some way to perform in-application-programming - and how that is then implemented.


  • See: http://www.keil.com/forum/59807 -
    in particular, the links to the so-called "bible" for the 8051 architecture.

    See also: http://www.keil.com/support/man/docs/c51/c51_le_pgmmem.htm

  • You may be able to find specific 8051 chips that can perform in-application-programming....
    all SILabs '51 chips (at least all I know) are able to write to code memory by a "switched movx"

    Erik

  • Ah ok, good to know.

    I apologize, I forgot to mention that I am using an R8051XC2 which is a soft-core version of the uP implemented on an FPGA. I am also using the KEIL IDE which does support the core version and has all of the details on the instruction set. From the website they say it is possible to write to program using the MOVC command, but seem hesitant about the memcpy writing to program mem.

    I am thinking a possible round about solution might be to write to a large chunk of external memory (XDATA) and designate that chunk as pseudo-ROM. BUT then I need to find out how to set the PC to the base location of that new memory chunk and run from there.

    This seems like a question for someone who know the exact uP I am using, but I really do appreciate non-specific answers.

    I just hope there is someway I can solve the problem even if it is not the best or even appropriate way of doing something like this.

    Thanks for your response!

  • Thanks, I will check this out.

  • I do not know your softcore, but: From the website they say it is possible to write to program using the MOVC command,
    that would not be possible, the MOVC command is unidirectional.

    BUT then I need to find out how to set the PC to the base location of that new memory chunk
    and run from there.

    Unless your softcore support "relocatable vectors" (which would be VERY strange for a '51 implementation), you can't do that

  • Well, if they say that, then get them to show you how!

    But that would be a completely non-standard implementation of the 8051 instruction set - so you would need a special compiler that can generate this bastardised code.

    Keil does support some extensions to the standard architecture - check here: http://www.keil.com/support/man/docs/c51/c51_dv_8051deriv.htm

    See also: http://www.keil.com/support/man/docs/c51/c51_cm_dirlist.htm

  • Yes - as you are relying on some very specific, non-standard features of that core.

  • I solved my problem.

    MOV     PCON, #10h
    MOV     DPTR, #0B00h
    MOV     A, #11h
    MOVX    @DPTR, A
    

    This will move immediate value 0x11 to program memory location 0B00. And yes I know I am relying on specific extensions to the microprocessor (it is developed by CAST Inc.), that was the rational for choosing this microprocessor.

  • Actually, as far as the 8051 core is concerned, it moves the value to XDATA memory - that is the definition of the MOVx instruction.

    You are relying on some external hardware trickery to map that XDATA address into your CODE space.

    The good thing here is tht you can do it just as well in 'C' - you don't need any special assembler magic.

    We could do the same with the late Triscend E5 - simply update the mapping registers which controlled the mapping of the 8051 core's XDATA and CODE spaces to the external, linear physical address space.

    Note also that updating Flash (nothing to do with 8051) is not as simple as just a write operation - a previous erase is generally required...

  • Probably more precise to say, "... map that XDATA address into the same physical address that your CODE space is mapped into"

    Maybe something like this

    
                           +----------+
                           | Physical |
                           |          |
                           |          |
               +-------+   |          |
               | CODE  |   |          |
               |       |   |          |
    +-------+  |       |   |          |
    | XDATA |  |       |   |          |
    |       |  |       |   |          |
    |       |  |       |   |          |
    |       |  |       |   |          |
    |       |  |       |   |          |
    |       |  +-------+   |          |
    |       |              |          |
    |       |              |          |
    +-------+              |          |
                           |          |
                           |          |
                           |          |
                           +----------+
    

  • The core is just the core, remember this is a soft-core put onto an FPGA, which is different from a DIP chip 8051 for example.

    Below I have posted a verbatim copy of what the user manual says, which states that I am actually placing 0x11 into real program memory space. Setting the pwm bit changes the function of MOVX.

    The previous erase may be something I need to consider when I begin to implement the code, but I will find a way to make it work.

    2.3.5 Program memory write mode
    The Program Memory Write mode allows full access to the program memory address space.
    The Program Memory Write feature is an extension to the 8051 instruction set but does not
    require modification of the standard code. It is enabled using parameter called
    PMW_IMPLEMENT=1 (0=disabled).

    Table 9. Program Memory Write Configuration
    PMW_IMPLEMENT Action
    0 Program Memory Write disabled (“pmw” bit of “pcon” not implemented)
    1 (default) Program Memory Write can be enabled by setting “pmw” bit of “pcon”
    register
    The MOVX instructions perform one of two actions depending on the state of “pmw” bit
    (pcon.4). The “pmw” bit selects the standard or advanced behavior of the microcontroller
    during execution of MOVX instruction.
    When the “pmw” is cleared or after reset, MOVX instructions allow read/write access to
    external data memory space. The software can set the “pmw” bit to enable access to program
    memory space. Once the “pmw” bit is set, MOVX data memory instructions become MOVX
    program memory instructions with 8 or 16-bit addressing modes. The software clears the
    “pmw” bit to switch back to normal MOVX behavior.
    Setting or clearing the “pmw” bit does not influence the execution of MOVC instruction and it
    does not change the behavior of program memory reading.