# Running the "perf_xfile" example on an STM32F746IGT6-based board with SD Card

This page describes the steps required to build and run the `perf_xfile` example on an STM32F746IGT6 evaluation board equipped with an SD card.

The `perf_xfile` example demonstrates how to use external storage (e.g., an SD card) with eXtremeDB/rt.

The STM32F746IGT6-based board has the following specifications:

- CPU: ARM 32-bit Cortex-M7 with FPU
- Maximum frequency: 216 MHz
- On-chip flash: 1 MB NOR XIP flash
- RAM: 320 KB
- External storage: 32 GB SD card (connected via SPI)

The SD card is connected via the SPI bus and serves as persistent storage for the database.

As shown, the board’s resources are relatively constrained, making it representative of a mid-range target in the embedded systems landscape.

Note: Development for STM32 microcontrollers is typically performed using STM32CubeIDE.

## Building the Project

To build and run the `perf_xfile` example, follow these steps:

1. Create a new empty project in STM32CubeIDE for the STM32F746IGTx target.

2. Use STM32CubeMX to generate a default configuration for this target.

3. In the configuration:

   - Enable UART (required to view example output via serial console).
   - Set the system clock (SYSCLK) to 200 MHz.

4. Enable the SPI peripheral (or peripherals, if needed) and ensure the APB2 peripheral clock is set to 100 MHz. Configure the SPI interface as follows:

   - Mode: Full-Duplex Master
   - Hardware NSS signal: Hardware NSS Output Signal
   - Frame Format: Motorola
   - Data Size: 8 bits
   - First Bit: MSB First
   - Prescaler (baud rate): 256
   - Clock Polarity (CPOL): Low
   - Clock Phase (CPHA): 1 Edge
   - CRC Calculation: Disabled
   - NSSP Mode: Enabled
   - NSS Signal Type: Output Hardware

5. In the project’s linker script (`.ld` file), configure the heap and stack sizes as follows. Database memory will be allocated dynamically via `malloc()`:

           _Min_Heap_Size = 0x40000; /* 256 KB heap */
           _Min_Stack_Size = 0x4000; /* 64 KB stack */

6. After saving the configuration and generating the startup code, verify that the basic project builds and runs correctly on the target hardware.

7. In the eXtremeDB/rt package, generate the database schema code for the `perf_xfile` example:

           cd eXtremeDB_rt/samples/perf_xfile
           ../../host/bin/mcocomp -x32 schema.mco

8. Add the following files from the eXtremeDB/rt package to your project source tree. This includes the eXtremeDB/rt core, the MURSIW transaction manager, persistent storage support, and the SD card driver over SPI:

           ./include/mcoewslite.h
           ./include/mcoflashsim.h
           ./include/mco.h
           ./include/mco.hpp
           ./include/mconet.h
           ./include/mcoquad.h
           ./include/mcorestrt.h
           ./include/mcosmint.h
           ./include/mcosmp.h
           ./include/mcospec.h
           ./include/mcossl.h
           ./include/mcostatrt.h
           ./include/mcotargt.h
           ./include/mcotime.h
           ./include/mcotrace.h
           ./include/mcouda.h
           ./include/mcovers.h
           ./include/mcowrap.h
           ./samples/perf_xfile/main.c
           ./samples/perf_xfile/perf.c
           ./samples/perf_xfile/perf.h
           ./samples/perf_xfile/schema.mco
           ./target/crypt/mcocryptstub.c
           ./target/mcolib/mcoabst.c
           ./target/mcolib/mcoabst.h
           ./target/mcolib/mcoamp.c
           ./target/mcolib/mcoamp.h
           ./target/mcolib/mcoautoid.c
           ./target/mcolib/mcoautoid.h
           ./target/mcolib/mcobmap.h
           ./target/mcolib/mcobse.h
           ./target/mcolib/mcobtree.c
           ./target/mcolib/mcocfg.h
           ./target/mcolib/mcocmpkt.c
           ./target/mcolib/mcocobj.c
           ./target/mcolib/mcocobj.h
           ./target/mcolib/mcoconn.c
           ./target/mcolib/mcoconn.h
           ./target/mcolib/mcoconst.h
           ./target/mcolib/mcocont.c
           ./target/mcolib/mcocryptmem.c
           ./target/mcolib/mcocryptmem.h
           ./target/mcolib/mcocsr.c
           ./target/mcolib/mcocsr.h
           ./target/mcolib/mcodb.c
           ./target/mcolib/mcodb.h
           ./target/mcolib/mcodict.c
           ./target/mcolib/mcodict.h
           ./target/mcolib/mcodiskbtree.h
           ./target/mcolib/mcodisk.h
           ./target/mcolib/mcodup.c
           ./target/mcolib/mcoerr.h
           ./target/mcolib/mcoevasy.c
           ./target/mcolib/mcoevasy.h
           ./target/mcolib/mcoevsyn.c
           ./target/mcolib/mcoevsyn.h
           ./target/mcolib/mcohash.c
           ./target/mcolib/mcoindex.c
           ./target/mcolib/mcoindex.h
           ./target/mcolib/mcomd.c
           ./target/mcolib/mcomembtree.c
           ./target/mcolib/mcomembtree.h
           ./target/mcolib/mcomem.h
           ./target/mcolib/mcoobj.c
           ./target/mcolib/mcoobj.h
           ./target/mcolib/mcoorder.c
           ./target/mcolib/mcopage.c
           ./target/mcolib/mcopmbuf.c
           ./target/mcolib/mcopmbuf.h
           ./target/mcolib/mcoproto.h
           ./target/mcolib/mcorec.c
           ./target/mcolib/mcortmt.c
           ./target/mcolib/mcortree_core.c
           ./target/mcolib/mcortreeu.c
           ./target/mcolib/mcortreeu.h
           ./target/mcolib/mcortst.c
           ./target/mcolib/mcoseri.h
           ./target/mcolib/mcoshm0.c
           ./target/mcolib/mcoshm.h
           ./target/mcolib/mcoshmu.c
           ./target/mcolib/mcostat.c
           ./target/mcolib/mcostatimpl.h
           ./target/mcolib/mcosys.h
           ./target/mcolib/mcothash.c
           ./target/mcolib/mcotmgr.h
           ./target/mcolib/mcotrans.c
           ./target/mcolib/mcotrans.h
           ./target/mcolib/mcowarr.c
           ./target/mcolib/mcowev.c
           ./target/mcolib/mcowfnd.c
           ./target/mcolib/mcowimp.c
           ./target/mcolib/mcowimp.h
           ./target/mcolib/mcowobj.c
           ./target/mcolib/mcowoid.c
           ./target/mcolib/mcowrap.c
           ./target/mcolib/mcowvec.c
           ./target/mcomd/mcomconv.c
           ./target/mcoseri/mcobse.c
           ./target/mcoseri/mcoseri.c
           ./target/mcoseri/mcosericmn.c
           ./target/mcotrace/mcoasynctrace.c
           ./target/mcotrace/mcostrerror.c
           ./target/mcotrace/mcotrace.c
           ./target/mcotrace/mcotracehandlers.c
           ./target/mcovtdsk/mcodiskbtree.c
           ./target/mcovtdsk/mcodisk.c
           ./target/mcovtdsk/mcovtdsk.c
           ./target/mcovtdsk/mcoxfile/mcoxfile.c
           ./target/misc/mcobmap.c
           ./target/misc/mcocompress.c
           ./target/misc/mcoerr.c
           ./target/misc/mcoheap.c
           ./target/misc/mcosort.c
           ./target/misc/mcosort.d
           ./target/misc/mcostrrt.c
           ./target/sal/atomic/mcosalatomic.c
           ./target/sal/fsys/mcofsdcspi.c
           ./target/sal/latches/mcosallatches.c
           ./target/sal/mem/mcosysmem.c
           ./target/sal/smp/mcofreertos.c
           ./target/sal/smp/mconoos.c
           ./target/sal/smp/mcopool.c
           ./target/sal/sync/mcosnone.c
           ./target/sal/timer/mcosaltimer.c
           ./target/tmgr/mcotque.c
           ./target/tmgr/mcotuctrl.h
           ./target/tmgr/mursiw.c

9. Add the following include paths to your project settings:

           ../eXtremeDB_rt/include
           ../eXtremeDB_rt/target/mcolib
           ../eXtremeDB_rt/target/tmgr
           ../eXtremeDB_rt/samples/common

10. Add the following preprocessor definitions to your project settings:

            _ARM32
            STM32F746xx
            USE_HAL_DRIVER
            STM32F746IGTx
            STM32
            STM32F7
            MCO_TRACE_ENABLED=1
            MCO_TRACE_CONSOLE_SUPPORTED=1
            MCO_CONFIG_OVERRIDE_TRACE_FILE_ROTATION

11. Modify the example code in `samples/perf_xfile/main.c` so that the database resides on the SD card. During database initialization, the application must provide three devices:

    - A RAM segment for database metadata,
    - A RAM segment for the persistent device cache,
    - A persistent device representing the SD card (via an SPI bus handle).
    The database initialization code may look like this:

            #define P_DB_MODE_MASK            0
            #define P_DB_MEM_PAGE_SZ          512               /* in-memory page size */
            #define P_DB_DISK_PAGE_SZ         8192              /* persistent page size */
            #define P_DB_DISK_MAX_SIZE        (1024*1024*1024)  /* max size of persistent database */
            #define P_DB_SIZE                 (24 * 1024)       /* RAM for database metadata */
            #define P_DB_CACHE_SZ             (180 * 1024)      /* RAM for persistent device cache */

            mco_device_t    devices[3] = {0};
            mco_db_params_t db_params = {0};
            void *          media_context = &hspi1; /* SPI bus handle */

            devices[0].assignment = MCO_MEMORY_ASSIGN_DATABASE;
            devices[0].size       = P_DB_SIZE;
            devices[0].type       = MCO_MEMORY_CONV;
            devices[0].dev.conv.ptr = (char*)malloc(devices[0].size);
            devices[0].dev.conv.flags = 0;

            devices[1].assignment = MCO_MEMORY_ASSIGN_CACHE;
            devices[1].size       = P_DB_CACHE_SZ;
            devices[1].type       = MCO_MEMORY_CONV;
            devices[1].dev.conv.ptr = (char*)malloc(devices[1].size);
            devices[1].dev.conv.flags = 0;

            /* Persistent storage on SD card */
            devices[2].type       = MCO_MEMORY_FILE;
            devices[2].assignment = MCO_MEMORY_ASSIGN_PERSISTENT;
            sprintf(devices[2].dev.file.name, "SDCard @ %p", media_context);
            devices[2].dev.file.media_context = &media_context;
            devices[2].dev.file.media_context_size = sizeof(void*);
            devices[2].dev.file.flags = MCO_FILE_OPEN_WITH_MEDIA_CTX | MCO_FILE_OPEN_TRUNCATE | MCO_FILE_OPEN_DEFAULT;

            mco_db_params_init(&db_params);
            db_params.mode_mask              = P_DB_MODE_MASK;
            db_params.mem_page_size          = P_DB_MEM_PAGE_SZ;
            db_params.disk_page_size         = P_DB_DISK_PAGE_SZ;
            db_params.disk_max_database_size = P_DB_DISK_MAX_SIZE;
            db_params.db_max_connections     = 1;
            db_params.tlb_cache_lines        = 128;
            db_params.tlb_cache_ways         = 4;

            MCO_RET rc = mco_db_open_dev(db_name, perf_get_dictionary(), devices, 3, &db_params);

12. Modify the auto-generated `main.c` (from STM32CubeMX) to call the example entry point: `sample_main()`.

13. Build the project and flash it onto the STM32F746IGT6 board.

## Expected Output

After successful compilation and deployment, the `perf_xfile` example will execute on the target device. The output will appear on the UART console as follows:

        Insert               : .................... 1000 objects: 546 milliseconds,(546 microsecs/object)
        Random search        : .................... 1000 searches: 1 milliseconds (1 microsecs/search)
        Sequential search    : .................... 1000 searches: 40 milliseconds (40 microsecs/search)
        Random update        : .................... 1000 objects: 446 milliseconds (446 microsecs/object)
        Random delete        : .................... 1000 objects: 569 milliseconds (569 microsecs/object)