How to preserve RAM cell from being used - c

I use GNU for ARM and want to define some cell in RAM memory space as following:
#define FOO_LOCATION 0x20000000
#define foo (*((volatile uint32_t *) FOO_LOCATION ))
My question is - if such declaration will prohibit usage of the cell with FOO_LOCATION address in stack or heap? What address preffered to avoid memory fragmentation?
Update
I want to place some variable at a certain memory address and access it after watchdog reset. I guess that if i will declare it as usual
uint32_t foo;
it will have another physical location after reset. Also i read a post where said that most probably there is no such way to declare variable adddress. And i have idea to tell the GNU not to use some memory address. As for example special registers are not used by custom variables.
Update 2
In addition to previous definitions i added section to linker script
SECTIONS
{
. = 0x20000000
.fooSection :
{
*(.fooSection)
. = 0x04 /* size = 4 bytes */
}
/* other placements follow here... */
}

Related

Retroarch Memory Map undefined for PSX (Beetle PSX HW)

I am working on pulling data from Retroarch via JSON format using software called Gamehook.
I am trying to add support for the PSX with the Beetle PSX HW core.
The issue is that even with extensive searching through the core and retroarch's source code, I cannot find a proper memory map for it. I have tried adding the ranges from the two sources below, which gives me a "no memory map defined" error.
http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt
0x8000_0000 0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached
0xa000_0000 0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached
0x0000_0000-0x0000_ffff Kernel (64K)
0x0001_0000 0x001f_ffff User Memory (1.9 Meg)
0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes)
and
https://psx-spx.consoledev.net/memorymap/
KUSEG KSEG0 KSEG1
00000000h 80000000h A0000000h 2048K Main RAM (first 64K reserved for BIOS)
1F000000h 9F000000h BF000000h 8192K Expansion Region 1 (ROM/RAM)
1F800000h 9F800000h -- 1K Scratchpad (D-Cache used as Fast RAM)
1F801000h 9F801000h BF801000h 8K I/O Ports
1F802000h 9F802000h BF802000h 8K Expansion Region 2 (I/O Ports)
1FA00000h 9FA00000h BFA00000h 2048K Expansion Region 3 (SRAM BIOS region for DTL cards)
1FC00000h 9FC00000h BFC00000h 512K BIOS ROM (Kernel) (4096K max)
FFFE0000h (in KSEG2) 0.5K Internal CPU control registers (Cache Control)
Looking at consoleinfo.c in the Retroarch source code, it defines the memory regions for Playstation as.
/* ===== PlayStation ===== */
/* http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt */
static const rc_memory_region_t _rc_memory_regions_playstation[] = {
{ 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" },
{ 0x010000U, 0x1FFFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
};
static const rc_memory_regions_t rc_memory_regions_playstation = { _rc_memory_regions_playstation, 2 };
And the definition for rc_memory_region_t is
typedef struct rc_memory_region_t {
unsigned start_address; /* first address of block as queried by RetroAchievements */
unsigned end_address; /* last address of block as queried by RetroAchievements */
unsigned real_address; /* real address for first address of block */
char type; /* RC_MEMORY_TYPE_ for block */
const char* description; /* short description of block */
}
rc_memory_region_t;
I have asked in the Retroarch discord server and they have unfortunately given me conflicting information. Such as, I want to use the RetroAcheievements memory address or that I need to find out how Retroarch deals with memory addressing of the cores.
With that second portion, I have looked at the entire source code in depth and have only found the memory addressing information here.
So my question comes down to, does anyone know either how to find the mappable memory addresses from the cores in Retroarch or does anyone happen to know the mappable memory addresses from the cores in Retroarch?

Understanding the writing to flash process in the STM32 reference manual

I am programming the stm32l412kb where at one point I will be writing data to flash (from UART). From the stm32l41xx reference manual, I understand the steps in how to clear the memory before writing to it but on page 84 there is one step that I do not know how to do when writing the actual data. That step is the
Perform the data write operation at the desired memory address
What data write operation is it mentioning? I can't see any register the memory address goes to so I assume its going to use pointers? How would I go about doing this?
Your help is much appreciated,
Many thanks,
Harry
Apart from a couple of things (e.g. only write after erase, timings, alignment, lock/unlock) their ain't much difference between writing to RAM and writing to FLASH memory. So if you have followed the steps from the reference manual and the FLASH memory is ready (i.e. cleared and unlocked) then you can simply take an aligned memory address and write to it.
STMs very own HAL library contains a function which does all the cumbersome boilerplate for you and allows you to "just write":
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
Internally this function uses a subroutine which performs the actual write and it looks like this:
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
{
/* Check the parameters */
assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
/* Set PG bit */
SET_BIT(FLASH->CR, FLASH_CR_PG);
/* Program first word */
*(__IO uint32_t*)Address = (uint32_t)Data;
/* Barrier to ensure programming is performed in 2 steps, in right order
(independently of compiler optimization behavior) */
__ISB();
/* Program second word */
*(__IO uint32_t*)(Address+4U) = (uint32_t)(Data >> 32);
}
As you can see there is no magic involved. It's just a dereferenced pointer and an assignment.
What data write operation is it mentioning?
The "data write" is just a normal write to a address in memory that is the flash memory. It is usually the STR assembly instruction. Screening at your datasheet, I guess the flash memory addresses are between 0x08080000 and 0x00080000.
Ex. the following C code would write the value 42 to the first flash memory address:
*(volatile uint32_t*)0x00080000 = 42.
For a reference implementation you can see stm32 hal drivers:
/* Set PG bit */
SET_BIT(FLASH->CR, FLASH_CR_PG);
/* Program the double word */
*(__IO uint32_t*)Address = (uint32_t)Data;
*(__IO uint32_t*)(Address+4) = (uint32_t)(Data >> 32);

STM32, variable stored in flash could not be updated in other file

I use a STM32F411RE.
Since I've no more memory in my RAM. I decided to store large variable in my flash. For that I created a section in section.ld.
.large_buffer: ALIGN(4)
{
. = ALIGN(4) ;
*(.large_buffer.large_buffer.*)
. = ALIGN(4) ;
} >FLASH
In the main.c file, I declare the variable as follow :
uint8_t buffer[60 * 200] __attribute__ ((section(".large_buffer"), used));
At this point everything is OK, the buffer is not stocked in the RAM (bss), I can access it and rewrite it.
buffer[25] = 42;
printf("%d\n", buffer[25]); // 42
The problem comes when I want to edit the variable from an other file.
main.c
uint8_t buffer[60 * 200] __attribute__ ((section(".large_buffer"), used));
int main()
{
myFunc(buffer);
}
other.c
myFunc(uint8_t* buffer)
{
buffer[25] = 42;
printf("%d\n", buffer[25]); // 0
}
buffer never change in another file (passed as parameter).
Did I miss something ?
You cannot write to flash memory the same way as you write to RAM, because of physical design of flash memories. To be exact you need to erase sector/page (let's say ~ 1-4kB, it's specified in your MCU datasheet). The reason is that flash are made that they retain state even if they're not powered, whenever you want to change any bit from value 0 -> 1 you need to erase whole sector (After erase all of bits will be set to 1).
So you cannot use Flash as data memory, what you could do is use Flash as storing variables that are const (read-only) value, so any look-up tables will perfectly fit in there (usually compilers when you stat variable to const will put them inside of flash). How to write to flash you can read in Reference Manual of your MCU.

Align a variable in memory with offset from power of two in memory

I would like to place a 2kB chunk of memory, aligned 16 bytes before a 1024 bytes alignment.
Platform : arm, bare metal, GNU toolchain. No need for portability
Can I do that with either GCC/attributes pragmas, ld custom linker script or any other solution ?
I would like to avoid wasting 1kB for that (basically placing a 3kB chunk of memory aligned at 1kB & adding 1024-16 bytes of padding).
Forcing a particular address to place the data is possible, but will ld be able to place variables before and after it (or is it just a way to put padding ? )
Context : buffer needs to be at 1k boundary by hardware design , but I'd like to add a bit of room before / after to be able to copy to this buffer with no bounds checking if my source is at most 16B wide.
edit: added example.
Let's say I have RAM starting at 0x2000000. I need a char buf[2048] be placed in it, at 1024*N-16 offset - ie (&buf[16])%1024==0 , hopefully without losing 1008 padding bytes.
(edit2)
So I'd like to have :
0x2000000 - some vars
0x2000010 - some other vars ...
0x2000100 - some other vars ...
0x20003F0 - char buf[2048] : here (int)&buf[16]%1024=0x2000400%1024==0
0x2000BF0 - some other vars ...
ALIGN(exp) is equivalent to (. + exp - 1) & ~(exp - 1). Of course, that expression only works if exp is a power of two. So you can't use ALIGN(), but you can write your own expression that does produce the result you want. Something like ((. + 1024 + 16 - 1) & ~(1024 - 1)) - 16 should do the trick. Plug in various values for . and you see it rounds up like you want.
The problem you'll have is that the linker will place every section you specified to be before your special section before it, and every section specified to be after it after it. It won't cleverly order the .data sections of different files to be before or after so as to produce the minimum amount of padding. It also won't re-order individual variables within an object file and section at all. If you are trying to pack as tightly as possible, I think you'll need to do something like:
.data : {
*(.about1008bytes)
. = ((. + 1024 + 16 - 1) & ~(1024 - 1)) - 16
*(.DMAbuf)
*(.data)
}
Use a section attribute to place your buffer in .DMAbuf and try to find close to but not more than 1008 bytes of other data variables and stick them in section .about1008bytes.
If you want to go crazy, use gcc -fdata-sections to place every data object in its own section, extract the section sizes with readelf, give that to a program you write to sort them for optimal packing that then spits out a chunk of linker script listing them in the optimal order.
You should define a specific section into your linker script, with the required alignment.
Looking at the man
ALIGN(exp)
Return the result of the current location counter (.) aligned to the next exp boundary. exp must be an expression whose value is a power of two. This is equivalent to
(. + exp - 1) & ~(exp - 1)
ALIGN doesn't change the value of the location counter--it just does arithmetic on it. As an example, to align the output .data section to the next 0x2000 byte boundary after the preceding section and to set a variable within the section to the next 0x8000 boundary after the input sections:
SECTIONS{ ...
.data ALIGN(0x2000): {
*(.data)
variable = ALIGN(0x8000);
}
... }
The first use of ALIGN in this example specifies the location of a section because it is used as the optional start attribute of a section definition (see section Optional Section Attributes). The second use simply defines the value of a variable. The built-in NEXT is closely related to ALIGN.
As an example you can define your section
SECTIONS
{
.myBufBlock ALIGN(16) :
{
KEEP(*(.myBufSection))
} > m_data
}
and into your code you can
unsigned char __attribute__((section (".myBufSection"))) buf[2048];
EDIT
SECTIONS
{
.myBufBlock 0x0x7FBF0 :
{
KEEP(*(.myBufSection))
} > m_data
}
and into your code you can
unsigned char __attribute__((section (".myBufSection"))) buf[16+2048+16];
To your DMA you can set the address &buf[16] that will be 1k aligned.

Initialize array starting from specific address in memory - C programming

Do you have idea how to initialize array of structs starting from specific address in memory (not virtual, physical DDR memory). I am working on implementation of TxRx on SoC (ARM-FPGA). Basically ARM (PS) and FPGA (PL) communicate to each other by using shared RAM memory. Currently I am working on transmitter side, so I need to constantly load packets that I get from MAC layer to memory, then my Tx reads data and sends it in air. To achieve this I want to implement circular FIFO buffer on (ARM) side, in way that I can store up to 6 packets into buffer and send them one by one, in same time loading other packets on places of already sent packages. Because I need to use specific memory addresses I am interested is it possible to initialize array of structure that will be stored on specific addresses in memory. For example I want that my array starts at adress 0x400000 and ends at address 0x400000 + MaximumNumberOfPackets x SizeOfPackets I know how to do it for one instantiate of structure for example like this:
buffer_t *tmp = (struct buffer_t *)234881024;
But how to do it for array of structures?
A pointer to a single struct (or int, float, or anything else) is inherently a pointer to an array of them. The pointer type provides the sizeof() value for an array entry, and thus allows pointer arithmetic to work.
Thus, given a struct buffer you can simply do
static struct buffer * const myFIFO = (struct buffer *) 0x40000
and then simply access myFIFO as an array
for (size_t i = 0; i < maxPackets; ++i)
{
buffer[i].someField = initialValue1;
buffer[i].someOtherField = 42;
}
This works just the way you expect.
What you can't do (using pure standard C) is declare an array at a particular address like this:
struct buffer myFIFO[23] # 0x400000;
However, your compiler may have extensions to allow it. Many embedded compilers do (after all, that's often how they declare memory-mapped device registers), but it will be different for every compiler vendor, and possibly for every chip because it is a vendor extension.
GCC does allow it for AVR processors via an attribute, for example
volatile int porta __attribute__((address (0x600)));
But it doesn't seem to support it for an ARM.
Generally #kdopen is right but for arm you should create an entry in MEMORY section linker script that shows to linker where is your memory:
MEMORY
{
...
ExternalDDR (w) : ORIGIN = 0x400000, LENGTH = 4M
}
And than, when you are declaring variable just use the
__attribute__((section("ExternalDDR")))
I found the way how to do it. So could I do it like this. I set this into linker script:
MEMORY {
ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x00100000, LENGTH = 0x1FF00000
ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x00030000
ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00
DAC_DMA (w) : ORIGIN = 0xE000000, LENGTH = 64K
}
.dacdma : {
__dacdma_start = .;
*(.data)
__dacdma_end = .;
} > DAC_DMA
And then I set this into code
static buffer_t __attribute__((section("DAC_DMA"))) buf_pool[6];

Resources