diff --git a/.gitignore b/.gitignore index fa38fadba3cc8..030babedd6af6 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,4 @@ tools/gdb/__pycache__ /build .ccls-cache compile_commands.json -imx9-sdimage.img +imx9-sdimage.img \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0341964c7eecf..b2effa4c918a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,11 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) endif() +if(POLICY CMP0169) + # allow to call FetchContent_Populate directly + cmake_policy(SET CMP0169 OLD) +endif() + # Basic CMake configuration ################################################## set(CMAKE_CXX_EXTENSIONS OFF) @@ -812,6 +817,11 @@ if(CONFIG_BUILD_PROTECTED) $<$:supc++> $<$>:-Wl,--end-group>) + target_include_directories( + nuttx_user SYSTEM + PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/include_arch) + add_custom_command( OUTPUT User.map COMMAND ${CMAKE_NM} nuttx_user > User.map diff --git a/Documentation/applications/examples/leds_rust/index.rst b/Documentation/applications/examples/leds_rust/index.rst new file mode 100644 index 0000000000000..11ab85770f908 --- /dev/null +++ b/Documentation/applications/examples/leds_rust/index.rst @@ -0,0 +1,6 @@ +================================= +``leds_rust`` Toggle LEDs in Rust +================================= + +This is a simple test in Rust of the board LED driver at +``nuttx/drivers/leds/userled_*.c``. diff --git a/Documentation/applications/system/spi/index.rst b/Documentation/applications/system/spi/index.rst index 9c1ae3ed86b0b..71e0593de9a2e 100644 --- a/Documentation/applications/system/spi/index.rst +++ b/Documentation/applications/system/spi/index.rst @@ -2,7 +2,7 @@ ``spi`` SPI Tool ================ -The I2C tool provides a way to debug SPI related problems. This README file will +The SPI Tool provides a way to debug SPI related problems. This README file will provide usage information for the SPI tools. Contents @@ -29,10 +29,10 @@ Contents * ``set`` * ``verf`` -- I2C Build Configuration +- SPI Build Configuration * NuttX Configuration Requirements - * I2C Tool Configuration Options + * SPI Tool Configuration Options System Requirements ------------------- @@ -71,7 +71,7 @@ or:: nsh> spi ? -Here is an example of the help output. I shows the general form of the command +Here is an example of the help output. It shows the general form of the command line, the various SPI commands supported with their unique command line options, and a more detailed summary of the command SPI command options:: @@ -95,8 +95,8 @@ and a more detailed summary of the command SPI command options:: **Notes**: - An environment variable like $PATH may be used for any argument. -- Arguments are _sticky_. For example, once the SPI address is specified, that - address will be re-used until it is changed. +- Arguments are _sticky_. For example, once the SPI bus is specified, that + bus will be re-used until it is changed. **Warning**: @@ -117,7 +117,7 @@ SPI operation. Those arguments vary from command to command as described below. However, there is also a core set of common ``OPTIONS`` supported by all commands. So perhaps a better representation of the general SPI command would be:: - i2c [OPTIONS] [arguments] + spi [OPTIONS] [arguments] Where ``[OPTIONS]`` represents the common options and and arguments represent the operation-specific arguments. @@ -146,7 +146,7 @@ Environment Variables variables. Environment variables must be preceded with the special character ``$``. For example, ``PWD`` is the variable that holds the current working directory and so ``$PWD`` could be used as a command line argument. The use of environment -variables on the I2C tools command is really only useful if you wish to write +variables on the SPI tools command is really only useful if you wish to write NSH scripts to execute a longer, more complex series of SPI commands. Common Option Summary @@ -187,7 +187,7 @@ Common Option Summary Various SPI devices support different data widths. This option is untested. -- ``[-f freq]`` I2C frequency. Default: ``4000000`` Current: ``4000000`` +- ``[-f freq]`` SPI frequency. Default: ``4000000`` Current: ``4000000`` The ``[-f freq]`` sets the frequency of the SPI device. The default is very conservative. @@ -212,7 +212,9 @@ Exchange data: ``exch [OPTIONS] `` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This command triggers an SPI transfer, returning the data back from the far end. -As an example (with MOSI looped back to MISO):: + +As an example you can exchange (send and receive) 4 bytes (-x 4) on SPI2 (-b 2) using the command below with the ``loopback`` approach. +This approach requires that you connect the MOSI pin directly to the MISO pin (NOTE: SCLK and CS are not directly involved, but you still can see the clock and chip select waveforms if you decide to use an oscilloscope or more properly a logic analyzer to analyze these pins):: nsh> spi exch -b 2 -x 4 aabbccdd @@ -221,7 +223,7 @@ As an example (with MOSI looped back to MISO):: Note that the ``TX Data`` are always specified in hex, and are always two digits each, case insensitive. -I2C Build Configuration +SPI Build Configuration ----------------------- NuttX Configuration Requirements @@ -241,7 +243,7 @@ The SPI tools requires the following in your NuttX configuration: CONFIG_SPI_DRIVER=y The SPI tool will then use the SPI character driver to access the SPI bus. - These devices will reside at ``/dev/spiN`` where ``N`` is the I2C bus number. + These devices will reside at ``/dev/spiN`` where ``N`` is the SPI bus number. **Note**: The SPI driver ``ioctl`` interface is defined in ``include/nuttx/spi/spi.h``. diff --git a/Documentation/components/drivers/character/touchscreen.rst b/Documentation/components/drivers/character/touchscreen.rst index 00448e30afff0..ce47444ed2c0c 100644 --- a/Documentation/components/drivers/character/touchscreen.rst +++ b/Documentation/components/drivers/character/touchscreen.rst @@ -36,3 +36,31 @@ found in the following locations: ``boards////src/`` directory for boards that use an external touchscreen controller chip. + +Application Programming Interface +================================= + +The first thing to be done in order to use the touchscreen driver from an +application is to include the correct header filer. It contains the +Application Programming Interface to the driver. To do so, include + +.. code-block:: c + + #include + +Touchscreen driver is registered as a POSIX character device file into +``/dev`` namespace. It is necessary to open the device to get a file descriptor +for further operations. This can be done with standard POSIX ``open()`` call. + +The driver is accessed through ``read``, ``write``, ``poll`` and ``ioctl`` +interface, Following ``ioctl`` commands are available: + + * :c:macro:`TSIOC_GRAB` + +.. c:macro:: TSIOC_GRAB + +This command let the current handle has the device grabbed. When a handle grabs +a device it becomes sole recipient for all touchscreen events coming from the +device. An argument is an ``int32_t`` variable to enable or disable the grab. + + diff --git a/Documentation/components/drivers/special/i2c.rst b/Documentation/components/drivers/special/i2c.rst index fa722cbf2bd36..08d1464f31e3c 100644 --- a/Documentation/components/drivers/special/i2c.rst +++ b/Documentation/components/drivers/special/i2c.rst @@ -21,3 +21,11 @@ I2C Device Drivers - **Examples**: ``arch/z80/src/ez80/ez80_i2c.c``, ``arch/z80/src/z8/z8_i2c.c``, etc. + +- ``struct i2c_slaveops_s``. Each I2C slave device driver must implement + an instance of ``struct i2c_slaveops_s``. That structure defines a call + table with the following methods: + +- **Binding I2C Slave Drivers**. I2C slave drivers are normally directly + accessed by user code, We can read and write to device nodes using posix + interfaces. diff --git a/Documentation/components/paging.rst b/Documentation/components/paging.rst index 7adf8b2235cad..787fa57f161d1 100644 --- a/Documentation/components/paging.rst +++ b/Documentation/components/paging.rst @@ -65,7 +65,7 @@ allocates a physical page and maps it to the virtual memory space that triggered the page fault exception and then resumes execution from the same point where the page fault first occurred. -:ref:`knsh32_paging` simulates a device with 4MiB physical memory with 8MiB +:ref:`knsh_paging` simulates a device with 4MiB physical memory with 8MiB of virtual heap memory allocated for each process. This is possible by enabling on-demand paging. diff --git a/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst b/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst index 339f5064e7c3a..20d067d01bc5d 100644 --- a/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst +++ b/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst @@ -691,3 +691,22 @@ at 13.56 MHz and ISO/IEC 14443 A/MIFARE and NTAG. .. figure:: mfrc522_image.jpg :align: center + +bmp280 +------ + +Configures the NuttShell (nsh) over USB Serial (check usbserial configuration) and enables BMP280 Digital Pressure Sensor. +BMP280 has an I2C address that can be configure by SDO. Connecting SDO to GND results in slave +address 0x76, connection it to VDD results in slave address 0x77. This can be configured by enabling BMP280_I2C_ADDR_76 or BMP280_I2C_ADDR_77. This configuration uses I2C1 and slave address 0x77. + +NSH commands:: + + NuttShell (NSH) NuttX-12.6.0-RC1 + nsh> bmp280 + Absolute pressure [hPa] = 911.400024 + Temperature [C] = 26.110001 + nsh> bmp280 + Absolute pressure [hPa] = 932.650024 + Temperature [C] = 24.490000 + +There is a known issue where every time the sensor is initialized, the first measurement is wrong, please check https://github.com/apache/nuttx/issues/12421 for the latest updates on this issue. \ No newline at end of file diff --git a/Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst b/Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst new file mode 100644 index 0000000000000..797e7b90f65c1 --- /dev/null +++ b/Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst @@ -0,0 +1,320 @@ +============================= +Zynq UltraScale+ RFSoC ZCU111 +============================= + +The `ZCU111 `_ is a +development board based on the Zynq UltraScale+ RFSoC(XCZU28DR) from XilinX(AMD). + +Features +======== + +- **RF Data Converter** + - **12-bit ADC:** 8, Max Rate 4.096G + - **14-bit DAC:** 8, Max Rate 6.554G + - **SD-FEC:** SD-FEC +- **Memory** + - **PS DDR4:** 4GB 64-bit SODIMM + - **SD-Card:** Yes + - **M.2 SATA Connector:** Yes + - **QSPI:** 2 +- **Communications & Networking** + - **USB UART/JTAG:** 1 + - **RJ45:** 1 + - **SFP+:** 4 + - **USB 3.0:** 1 +- **Expansion Connectors** + - **FMC-HPC Connector:** 2 + - **PMOD:** 2 + - **RFMC 1.0:** 2 + - **QSPI:** 2 +- **Control & I/O** + - **I2C:** Yes + - **PMBUS:** Yes + - **JTAG PC4 Header:** Yes +- **Boot Options** + - **ISD Boot:** Yes + - **QSPI Boot:** Yes + - **JTAG Boot:** Yes +- **DDR4 SODIMM:** 4GB 64-bit, 2400MT/s, attached to Processor Subsystem (PS) + +Serial Console +============== + +Serial console for the PS: + +===== ======== ============= +Pin Signal Notes +===== ======== ============= +MIO18 UART0 TX USB UART COM0 +MIO19 UART0 RX USB UART COM0 +===== ======== ============= + +PS-side UART interface and is connected to the FTDI U34 FT4232HL USB-to-Quad-UART +bridge port B Connect ZCU111 to our computer with the USB Cable. On our computer +start a Serial Terminal and connect to the USB Serial Port at **115200 bps**. +NuttX will appear in the Serial Console when it boots on zcu111. + +LEDs and Buttons +================ + +The PS-side pushbutton SW19 is connected to MIO22 (pin U1.Y28). The PS-side LED DS50, +which is physically placed adjacent to the pushbutton, is connected to MIO23(pin U1.U29). + +Configurations +============== + +Each configuration is maintained in a sub-directory and can be selected as follow:: + + tools/configure.sh zcu111: + +Where is one of the following: + +jtag +---- + +Basic NuttShell configuration for JTAG boot mode (nsh console enabled in UART0, +UART and JTAG exposed via FT4232HL USB-to-Quad-UART bridge port and USB cable). + +nsh +--- + +Basic NuttShell configuration for Flash boot mode. We need create boot image with +zynqmp_fsbl.elf, zynqmp_pmufw.elf, bl31.elf and nuttx.elf in Vivado SDK or XSCT +shell. Also we need copy BOOT.BIN into SD Card(in SD card boot mode) or Flash it +into the QSPI FLASH(in QSPI boot mode). + +ARM64 Toolchain +=============== + +There are two ways to install the toolchain for Zynq MPSoC: +The first way is download the ARM64 Toolchain ``aarch64-none-elf`` from +`Arm GNU Toolchain Downloads `_. +Add the downloaded toolchain ``gcc-arm-...-aarch64-none-elf/bin`` +to the ``PATH`` Environment Variable such as: + +.. code-block:: console + + $ echo "export PATH=/home/username/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin:$PATH" >> ~/.profile + +You can edit your .profile files if you don't use bash. + +The second way is install Vivado SDK or Vitis development environment which included a complete +``aarch64-none-elf`` toolchain and we also add it to the ``PATH`` Environment Variable such as: + +.. code-block:: console + + $ echo "export PATH=/home/username/tools/Xilinx/SDK/2018.3/gnu/aarch64/lin/aarch64-none/bin:$PATH" >> ~/.profile + +You can edit your .profile files if you don't use bash. + +Note: nuttx.elf build by toolchain install in first way can't be debuged by Vivado SDK which use +toolchain of second way for gdb version incompatibility. + +Check the ARM64 Toolchain: + +.. code:: console + + $ aarch64-none-elf-gcc -v + +Building +======== + +There are two types of NuttX image for Zynq MPSoC: debug by JTAG and boot from FLASH. + +debug by jtag +------------- + +We just configure the NuttX project and build the project: + +.. code:: console + + $ cd nuttx + $ tools/configure.sh zcu111:jtag + $ make + +Set the Project to nuttx and Application to nuttx.elf for psu_cortexa53_0 in Vivado SDK Debug Configuration. +Just click Debug button then we can debug NuttX. + +boot from flash +--------------- + +To boot from FLASH, we have to create BOOT.BIN image and flash it into QSPI FLASH or SD card. To create BOOT.BIN +in addition to building nuttx.elf, we also need to build zynqmp_fsbl.elf, zynqmp_pmufw.elf and bl31.elf +To build nuttx.elf we just configure the NuttX project and build the project: + +.. code:: console + + $ cd nuttx + $ tools/configure.sh zcu111:nsh + $ make + +build bl31.elf +-------------- + +To build bl31.elf we should fetch Fetch sources of ARM Trusted Firmware (ATF) and checkout the tags that +corresponding to the SDK version. Take Vivado 2018.3 for example: + +.. code:: console + + $ git clone https://github.com/Xilinx/arm-trusted-firmware.git + $ cd arm-trusted-firmware + $ git checkout xilinx-v2018.3 + +By default, the Arm-trusted firmware builds for OCM space at address 0xFFFEA000, and ATF assume that UBoot +or nuttx.elf located at address 0x08000000. Then we just build bl31.elf with: + +.. code:: console + + $ make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 + +But, with DEBUG flag set to 1, it can't fit in OCM, so by default with DEBUG=1, it builds for DDR location +0x1000 with build flag DEBUG=1 mentioned while building. Alternatively, user has always an option to build +for the location of their choice by specifying the build flags ZYNQMP_ATF_MEM_BASE, ZYNQMP_ATF_MEM_SIZE while +building. The flag ZYNQMP_ATF_MEM_BASE specifies the base address of ATF and flag ZYNQMP_ATF_MEM_SIZE specifies +the maximum size the ATF image can be. what's more we can specifies the target address of Uboot or nuttx.elf +by PRELOADED_BL33_BASE. for zcu111:nsh configuration Example bl31 build command: + +.. code:: console + + $ make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 ZYNQMP_ATF_MEM_BASE=0x10000 ZYNQMP_ATF_MEM_SIZE=0x40000 PRELOADED_BL33_BASE=0x100000 + +If we don't dubug bl31 we just build bl31 in following command: + +.. code:: console + + $ make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 PRELOADED_BL33_BASE=0x100000 + +After the build process completes the bl31.elf binary is created within the /build/zynqmp/release/bl31 directory. + +build zynqmp_pmufw.elf +---------------------- + +The Platform Management Unit (PMU) in Zynq MPSoC has a Microblaze with 32 KB of ROM and 128 KB of RAM. The ROM is +pre-loaded with PMU Boot ROM (PBR) which performs pre-boot tasks and enters a service mode. For more details on PMU, +PBR and PMUFW load sequence, refer to Platform Management Unit (Chapter-6) in Zynq MPSoC TRM (UG1085). PMU RAM can +be loaded with a firmware (PMU Firmware) at run-time and can be used to extend or customize the functionality of PMU. +Some part of the RAM is reserved for PBR, leaving around 125.7 KB for PMU Firmware. +There are usually two flows to create and build a PMU Firmware image for the target, Xilinx Vitis or Vivado SDK IDE or +hsi command line. The PMU Firmware is provided as a template application for the PMU processor for any hardware platform +including the Zynq MPSoC device. The steps required to create and build it can be applied by selecting the appropriate +platform, processor, and template to create zynqmp_pmufw.elf. We can also create PMU Firmware from system hardware +project hdf file by hsi command line: + +.. code-block:: + + proc generate_pmufw {} { + if {[file exists pmu_fw/zynqmp_pmufw.elf] != 1} { + set pmufw_design [hsi::create_sw_design pmu_1 -proc psu_pmu_0 -app zynqmp_pmufw] + hsi::add_library libmetal + hsi::generate_app -dir pmu_fw -compile + return "pmu_fw/zynqmp_pmufw.elf" + } + return "pmu_fw/zynqmp_pmufw.elf" + } + +In order to call this procs, the user needs to open the hdf (hsi::open_hw_design): + +.. code-block:: + + proc create_pmufw {hdf} { + hsi::open_hw_design $hdf + set pmufw [generate_pmufw] + hsi::close_hw_design [hsi::current_hw_design] + } + +Create a TCL script with HSI commands above -> Create a TCL script with HSI commands above -> +Launch XSCT 2018.3 -> Change directory to the zipped directory -> source xsct_script.tcl -> +create_pmufw design_1_wrapper.hdf + +build zynqmp_fsbl.elf +--------------------- + +First Stage Bootloader (FSBL) for Zynq UltraScale+ MPSoC configures the FPGA with hardware bitstream (if it exists) +and loads the Operating System (OS) Image or Standalone (SA) Image or 2nd Stage Boot Loader image from the non-volatile +memory (SD/eMMC/QSPI) to Memory (DDR/TCM/OCM) and takes A53/R5 out of reset. It supports multiple partitions, and each +partition can be a code image or a bitstream. Each of these partitions, if required, will be authenticated and/or decrypted. +FSBL is loaded into OCM and handed off by CSU BootROM after authenticating and/or decrypting (as required) FSBL. +There are usually two flows to create and build a PMU Firmware image for the target, Xilinx Vitis or Vivado SDK IDE or +hsi command line. +To create FSBL by Vitis or Vivado SDK IDE just launch VITIS or Vivado SDK and do following flow: + +- Provide path where VITIS workspace and project need to be created. With this VITIS workspace will be created +- (Optional step) To work with local repos, Select "Xilinx" (ALT - x) -> Repositories. Against Local Repositories, + click on "New..." and provide path of the local repo +- Select File-->New-->Application Project to open "New Project" window, provide name for FSBL project +- In the “Platform” section, click on “Create a new platform from hardware (XSA)” and select pre-defined hardware platform for ZynqMP. + - Alternatively, to create a new/custom platform from a .xsa file, click on “+”, browse and select the XSA file and a new hardware platform is created. +- In the "Domain" window, select the processor psu_cortexa53_0/psu_cortexr5_0, OS as standalone and Language as C. +- Click Next and select "Zynq MP FSBL" +- Click "Finish" to generate the A53/R5 FSBL. This populates the FSBL code and also builds it (along with BSP) +- Debug prints in FSBL are now disabled by default. To enable debug prints, define symbol: FSBL_DEBUG_INFO. + - In VITIS this can be done by: right click on FSBL application project -> select “C/C++ Build Settings” -> “Tool Settings” tab -> Symbols (under ARM v8 gcc compiler) + - Click on Add (+) icon and Enter Value: FSBL_DEBUG_INFO, click on "OK" to close the "Enter Value" screen +- In case any of the source files (FSBL or BSP) need to be modified, browse the file, make the change and save the file, + build the project. elf file will be present in the Debug/Release folder of FSBL project. + +To create FSBL by XSCT command line just launch XSCT console and execute following TCL script with HSI commands: + +.. code-block:: + + proc generate_fsbl {} { + if {[file exists zynqmp_fsbl/zynqmp_fsbl.elf] != 1} { + set fsbl_design [hsi::create_sw_design fsbl_1 -proc psu_cortexa53_0 -app zynqmp_fsbl] + common::set_property APP_COMPILER "aarch64-none-elf-gcc" $fsbl_design + common::set_property -name APP_COMPILER_FLAGS -value "-DRSA_SUPPORT -DFSBL_DEBUG_INFO -DXPS_BOARD_ZCU111" -objects $fsbl_design + hsi::add_library libmetal + hsi::generate_app -dir zynqmp_fsbl -compile + } + return "zynqmp_fsbl/zynqmp_fsbl.elf" + } + +In order to call this procs, the user needs to open the hdf (hsi::open_hw_design): + +.. code-block:: + + proc create_fsbl {hdf} { + hsi::open_hw_design $hdf + set fsbl [generate_fsbl] + hsi::close_hw_design [hsi::current_hw_design] + } + +Create a TCL script with HSI commands above -> Create a TCL script with HSI commands above -> +Launch XSCT 2018.3 -> Change directory to the zipped directory -> source xsct_script.tcl -> +create_fsbl design_1_wrapper.hdf + +generate BOOT.bin image +----------------------- + +You can create BOOT.bin images using the BIF attributes and the Bootgen command. +For this configuration, the BIF file(named fsbl.bif) contains the following attributes: + +.. code-block:: + + the_ROM_image: + { + [fsbl_config]a53_x64 + [bootloader]zynqmp_fsbl.elf + [pmufw_image]zynqmp_pmufw.elf + [destination_cpu = a53-0, exception_level = el-3, trustzone]bl31.elf + [destination_cpu = a53-0, exception_level = el-1]nuttx.elf + } + +The Vitis IDE calls the following Bootgen command to generate the BOOT.bin image for this configuration: + +.. code-block:: + + bootgen -image fsbl.bif -arch zynqmp -o .\BOOT.bin + +Flash BOOT.bin to QSPI FLASH +---------------------------- + +We can flash BOOT.bin into QSPI FLASH in following flow: + +- In the Vivado SDK/Vitis IDE, select Xilinx -> Program Flash. +- In the Program Flash wizard, browse to and select the BOOT.bin image file that was created as a part of this example. +- Select **qspi-x8-dual_parallel** as the Flash type. +- Set the Offset as 0 and select the BOOT.bin file. +- Click Program to start the process of programming the QSPI flash with the BOOT.bin. +- Wait until you see the message “Flash Operation Successful” in the console. + +Set mode switch SW6 to QSPI32, NuttX will appear in the Serial Console when we power on zcu111. diff --git a/Documentation/platforms/arm64/zynq-mpsoc/index.rst b/Documentation/platforms/arm64/zynq-mpsoc/index.rst new file mode 100644 index 0000000000000..e254e9eaa614d --- /dev/null +++ b/Documentation/platforms/arm64/zynq-mpsoc/index.rst @@ -0,0 +1,81 @@ +====================== +Zynq UltraScale+ MPSoC +====================== + +The Zynq UltraScale+ MPSoC family consists of a system-on-chip (SoC) style integrated +processing system (PS) and a Programmable Logic (PL) unit, providing an extensible and +flexible SoC solution on a single die.There's 64-bit Quadcore ARM Cortex-A53 Processors +and Dualcore ARM Cortex-R5 Real-Time Processors in the MPSoC, zynq-mpsoc given support +for Quadcore ARM Cortex-A53 Processors of MPSoC + +Peripheral Support +================== + +The following list indicates peripherals supported in NuttX: + +========== ======= =============== +Peripheral Support Notes +========== ======= =============== +MIO Yes +EMIO Yes Depending on PL +I2C No +CAN No +NET No +SPI No +QSPI No +TIMER NO +UART Yes +WDT No +DMA No +SDI No +ADC No Depending on PL +DAC No Depending on PL +PCI NO Depending on PL +========== ======= =============== + +MIO/EMIO +-------- + +Key features of the GPIO peripheral are summarized as follows: + +- 78 GPIO interfaces to the device pins. + - Routed through the MIO multiplexer. + - Programmable I/O drive strength, slew rate, and 3-state control. +- 96 GPIO interfaces to the PL (four allocated by software to reset PL logic). + - Routed through the EMIO interface. + - Data inputs. + - Data outputs. + - Output enables. +- I/O interface is organized into six banks (3 MIO and 3 EMIO). + +Pins can be configured/operated using ``zynq_mio_*`` functions. To handled 96 GPIO in 3 +EMIO banks you should map GPIO to chip's pin by HDL design in PL logic. + +UART +---- + +Zynq UltraScale+ MPSoC have two high-speed UARTs (up to 1Mb/s). The UART controller is +a full-duplex asynchronous receiver and transmitter that supports a wide range of +programmable baud rates and I/O signal formats. The controller can accommodate +automatic parity generation and multi-master detection mode this may introduce a large +number of interrupts which may be undesirable. + +UART can be configured/operated using ``zynq_uart_*`` functions. Both receive and +transmit can be operated in interrupt mode and polling mode. + +Psci and debug +-------------- + +Default exception level is EL1 for the NuttX OS. However, if we debug NuttX by JTAG +the XSCT of Vivado SDK will set the Zynq MPSoC to EL3. so have to config NuttX to run on +EL3. Other levels are not supported at the moment. And in this operating conditon +we can't use SMC for there's no ATF support. + +Supported Boards +================ + +.. toctree:: + :glob: + :maxdepth: 1 + + boards/*/* diff --git a/Documentation/platforms/risc-v/esp32c3-legacy/index.rst b/Documentation/platforms/risc-v/esp32c3-legacy/index.rst index 074d86919feb0..756c0925fd621 100644 --- a/Documentation/platforms/risc-v/esp32c3-legacy/index.rst +++ b/Documentation/platforms/risc-v/esp32c3-legacy/index.rst @@ -110,35 +110,75 @@ Note that this step is required only one time. Once the bootloader and partitio table are flashed, we don't need to flash them again. So subsequent builds would just require: ``make flash ESPTOOL_PORT=/dev/ttyUSBXX`` -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== -Download and build OpenOCD from Espressif, that can be found in -https://github.com/espressif/openocd-esp32 +Espressif uses a specific version of OpenOCD to support ESP32-C3: `openocd-esp32 `_. -If you have an ESP32-C3 ECO3, no external JTAG is required to debug, the ESP32-C3 -integrates a USB-to-JTAG adapter. +Please check `Building OpenOCD from Sources `_ +for more information on how to build OpenOCD for ESP32-C3. + +ESP32-C3 has a built-in JTAG circuitry and can be debugged without any additional chip. +Only an USB cable connected to the D+/D- pins is necessary: + +============ ========== +ESP32-C3 Pin USB Signal +============ ========== +GPIO18 D- +GPIO19 D+ +5V V_BUS +GND Ground +============ ========== + +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. OpenOCD can then be used:: openocd -c 'set ESP_RTOS none' -f board/esp32c3-builtin.cfg -For versions prior to ESP32-C3 ECO3, an external JTAG adapter is needed. -It can be connected as follows:: +If you want to debug with an external JTAG adapter it can +be connected as follows: - TMS -> GPIO4 - TDI -> GPIO5 - TCK -> GPIO6 - TDO -> GPIO7 +============ =========== +ESP32-C6 Pin JTAG Signal +============ =========== +GPIO4 TMS +GPIO5 TDI +GPIO6 TCK +GPIO7 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS none' -f board/esp32c3-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/esp32c3/index.rst b/Documentation/platforms/risc-v/esp32c3/index.rst index c08d990757f9d..e8c68758b8f78 100644 --- a/Documentation/platforms/risc-v/esp32c3/index.rst +++ b/Documentation/platforms/risc-v/esp32c3/index.rst @@ -120,35 +120,75 @@ Where ```` is typically ``/dev/ttyUSB0`` or similar and ``./`` is the path to the folder containing the externally-built 2nd stage bootloader for the ESP32-C3 as explained above. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32-C3: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32-C3. -If you have an ESP32-C3 ECO3, no external JTAG is required to debug, the ESP32-C3 -integrates a USB-to-JTAG adapter. +ESP32-C3 has a built-in JTAG circuitry and can be debugged without any additional chip. +Only an USB cable connected to the D+/D- pins is necessary: + +============ ========== +ESP32-C3 Pin USB Signal +============ ========== +GPIO18 D- +GPIO19 D+ +5V V_BUS +GND Ground +============ ========== + +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c3-builtin.cfg -For versions prior to ESP32-C3 ECO3, an external JTAG adapter is needed. -It can be connected as follows:: +If you want to debug with an external JTAG adapter it can +be connected as follows: - TMS -> GPIO4 - TDI -> GPIO5 - TCK -> GPIO6 - TDO -> GPIO7 +============ =========== +ESP32-C6 Pin JTAG Signal +============ =========== +GPIO4 TMS +GPIO5 TDI +GPIO6 TCK +GPIO7 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c3-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/esp32c6/index.rst b/Documentation/platforms/risc-v/esp32c6/index.rst index 72891f568dd90..6a51d3cf8e43e 100644 --- a/Documentation/platforms/risc-v/esp32c6/index.rst +++ b/Documentation/platforms/risc-v/esp32c6/index.rst @@ -119,35 +119,66 @@ Where ```` is typically ``/dev/ttyUSB0`` or similar and ``./`` is the path to the folder containing the externally-built 2nd stage bootloader for the ESP32-C6 as explained above. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== -Download and build OpenOCD from Espressif, that can be found in -https://github.com/espressif/openocd-esp32 +Espressif uses a specific version of OpenOCD to support ESP32-C6: `openocd-esp32 `_. + +Please check `Building OpenOCD from Sources `_ +for more information on how to build OpenOCD for ESP32-C6. You do not need an external JTAG to debug, the ESP32-C6 integrates a USB-to-JTAG adapter. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c6-builtin.cfg If you want to debug with an external JTAG adapter it can -be connected as follows:: +be connected as follows: - TMS -> GPIO4 - TDI -> GPIO5 - TCK -> GPIO6 - TDO -> GPIO7 +============ =========== +ESP32-C6 Pin JTAG Signal +============ =========== +GPIO4 TMS +GPIO5 TDI +GPIO6 TCK +GPIO7 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwtread; set ESP_FLASH_SIZE 0' -f board/esp32c6-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/esp32h2/index.rst b/Documentation/platforms/risc-v/esp32h2/index.rst index a06b036bbb8de..38bff47fb1795 100644 --- a/Documentation/platforms/risc-v/esp32h2/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/index.rst @@ -119,35 +119,66 @@ Where ```` is typically ``/dev/ttyUSB0`` or similar and ``./`` is the path to the folder containing the externally-built 2nd stage bootloader for the ESP32-H2 as explained above. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== -Download and build OpenOCD from Espressif, that can be found in -https://github.com/espressif/openocd-esp32 +Espressif uses a specific version of OpenOCD to support ESP32-H2: `openocd-esp32 `_. -You don not need an external JTAG is to debug, the ESP32-H2 integrates a +Please check `Building OpenOCD from Sources `_ +for more information on how to build OpenOCD for ESP32-H2. + +You do not need an external JTAG to debug, the ESP32-H2 integrates a USB-to-JTAG adapter. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32h2-builtin.cfg If you want to debug with an external JTAG adapter it can -be connected as follows:: +be connected as follows: - TMS -> GPIO2 - TDI -> GPIO5 - TCK -> GPIO5 - TDO -> GPIO3 +============ =========== +ESP32-H2 Pin JTAG Signal +============ =========== +GPIO2 TMS +GPIO5 TDI +GPIO4 TCK +GPIO3 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32h2-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst index e0a2a8a2b37af..34f137e6fd2e6 100644 --- a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst +++ b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst @@ -59,7 +59,7 @@ All of the configurations presented below can be tested by running the following $ ./tools/configure.sh rv-virt: -Where is the name of the configuration you want to use, i.e.: nsh, knsh32, knsh64... +Where is the name of the configuration you want to use, i.e.: nsh, knsh, knsh64... To build it, run the following command:: @@ -146,7 +146,7 @@ To run it with QEMU, use the following command:: knetnsh64 --------- -Similar to the `knsh32`_ configuration, but with networking support and 64-bit RISC-V. +Similar to the `knsh`_ configuration, but with networking support and 64-bit RISC-V. To run it with QEMU, use the following command:: @@ -169,7 +169,7 @@ knetnsh64_smp Similar to the `knetnsh64`_ configuration, but with SMP support for 64-bit RISC-V. -knsh32 +knsh ------ This is similar to the `nsh`_ configuration except that NuttX @@ -192,12 +192,12 @@ In `nsh`, applications can be run from the `/system/bin` directory:: nsh> /system/bin/hello -.. _knsh32_paging: +.. _knsh_paging: -knsh32_paging +knsh_paging ------------- -Similar to ``knsh32_romfs``, but enabling on-demand paging: this +Similar to ``knsh_romfs``, but enabling on-demand paging: this configuration simulates a 4MiB device (using QEMU), but sets the number of heap pages equal to ``CONFIG_ARCH_HEAP_NPAGES=2048``. This means that each process's heap is 8MiB, whereas ``CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE`` is @@ -208,10 +208,10 @@ to have their own address space larger than the available physical memory. This is particularly useful for implementing a set of programming language interpreters. -knsh32_romfs +knsh_romfs ------------ -Similar to the `knsh32`_ configuration, but uses ROMFS instead of `hostfs`. +Similar to the `knsh`_ configuration, but uses ROMFS instead of `hostfs`. A ROMFS image is generated and linked to the kernel. This requires re-running ``make``:: $ make V=1 -j$(nproc) @@ -234,7 +234,7 @@ In `nsh`, applications can be run from the `/system/bin` directory:: knsh64 ------ -Similar to the `knsh32`_ configuration, but for 64-bit RISC-V. +Similar to the `knsh`_ configuration, but for 64-bit RISC-V. Run it with QEMU using the default command for 64-bit RISC-V. @@ -257,6 +257,11 @@ leds64 Similar to the `nsh64`_ configuration, but with User LEDs support for 64-bit RISC-V. +leds64_rust +----------- + +Similar to the `leds64`_ configuration, but with ``leds_rust`` example enabled. + netnsh ------ diff --git a/Documentation/platforms/sim/sim/boards/sim/index.rst b/Documentation/platforms/sim/sim/boards/sim/index.rst index 472bfdabfd186..2026534ffcc91 100644 --- a/Documentation/platforms/sim/sim/boards/sim/index.rst +++ b/Documentation/platforms/sim/sim/boards/sim/index.rst @@ -849,16 +849,7 @@ NOTES: apps/examples/hello. - 2. This version has password protection enabled. Here is the login info:: - - USERNAME: admin - PASSWORD: Administrator - - The encrypted password is retained in /etc/passwd. I am sure that - you will find this annoying. You can disable the password protection - by de-selecting CONFIG_NSH_CONSOLE_LOGIN=y. - - 3. This configuration has BINFS enabled so that the builtin applications can + 2. This configuration has BINFS enabled so that the builtin applications can be made visible in the file system. Because of that, the builtin applications do not work as other examples. @@ -1807,6 +1798,21 @@ This is a configuration with sim usbhost support. Run sim usbhost with root mode, run sim usbdev or plug-in cdcacm usb device. Then you can use /dev/ttyACM to transfer data. +login +----- + +This is a configuration with login password protection for nuttx shell. + +NOTES: + + This config has password protection enabled. Here is the login info:: + + USERNAME: admin + PASSWORD: Administrator + + The encrypted password is retained in /etc/passwd. I am sure that + you will find this annoying. You can disable the password protection + by de-selecting CONFIG_NSH_CONSOLE_LOGIN=y. README.txt ========== diff --git a/Documentation/platforms/xtensa/esp32/index.rst b/Documentation/platforms/xtensa/esp32/index.rst index d8559a71b1388..115159d646483 100644 --- a/Documentation/platforms/xtensa/esp32/index.rst +++ b/Documentation/platforms/xtensa/esp32/index.rst @@ -142,8 +142,10 @@ externally-built 2nd stage bootloader and the partition table (if applicable): w ``make bootloader``, these files are placed into ``nuttx`` folder. ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32. @@ -165,10 +167,33 @@ Some boards, like :ref:`ESP32-Ethernet-Kit V1.2 `. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for configuring the JTAG adapter of the :ref:`ESP32-Ethernet-Kit V1.2 ` and + :ref:`ESP-WROVER-KIT ` boards and other FT2232-based JTAG adapters. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32-wrover-kit-1.8v.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + xtensa-esp32-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/xtensa/esp32s2/index.rst b/Documentation/platforms/xtensa/esp32s2/index.rst index 47037b72e66bd..93aa992b4a43f 100644 --- a/Documentation/platforms/xtensa/esp32s2/index.rst +++ b/Documentation/platforms/xtensa/esp32s2/index.rst @@ -135,8 +135,10 @@ externally-built 2nd stage bootloader and the partition table (if applicable): w ``make bootloader``, these files are placed into ``nuttx`` folder. ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32-S2: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32-S2. @@ -157,10 +159,33 @@ Some boards, like :ref:`ESP32-S2-Kaluga-1 Kit v1.3 `_ + for configuring the JTAG adapter of the :ref:`ESP32-S2-Kaluga-1 ` board + and other FT2232-based JTAG adapters. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32s2-kaluga-1.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + xtensa-esp32s2-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/xtensa/esp32s3/index.rst b/Documentation/platforms/xtensa/esp32s3/index.rst index a16c2659ac255..23d64b3a517fe 100644 --- a/Documentation/platforms/xtensa/esp32s3/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/index.rst @@ -142,8 +142,10 @@ externally-built 2nd stage bootloader and the partition table (if applicable): w ``make bootloader``, these files are placed into ``nuttx`` folder. ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32-S3: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32-S3. @@ -154,10 +156,32 @@ extra wiring/cable to connect JTAG to ESP32-S3. Most of the ESP32-S3 boards have USB connector that can be used for JTAG debugging. This is the case for the :ref:`ESP32-S3-DevKit ` board. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32s3-builtin.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + xtensa-esp32s3-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fab5dd53ffb85..2d174dccfea5b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -797,6 +797,7 @@ config ARCH_CORTEXM0 select ARM_THUMB select ARCH_ARMV6M select ARCH_HAVE_IRQPRIO + select ARCH_HAVE_RAMVECTORS select ARCH_HAVE_RESET select ARCH_HAVE_HARDFAULT_DEBUG diff --git a/arch/arm/include/armv6-m/irq.h b/arch/arm/include/armv6-m/irq.h index e900b6b1c5adb..335e81c2bd04e 100644 --- a/arch/arm/include/armv6-m/irq.h +++ b/arch/arm/include/armv6-m/irq.h @@ -330,6 +330,19 @@ static inline void setcontrol(uint32_t control) : "memory"); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h index 1bc4ce0ce5c1a..61437233f770c 100644 --- a/arch/arm/include/armv7-a/irq.h +++ b/arch/arm/include/armv7-a/irq.h @@ -406,6 +406,19 @@ noinstrument_function static inline void up_irq_restore(irqstate_t flags) ); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h index cfa94f44e504f..8a9e1f801ffdf 100644 --- a/arch/arm/include/armv7-m/irq.h +++ b/arch/arm/include/armv7-m/irq.h @@ -535,6 +535,19 @@ static inline void setcontrol(uint32_t control) : "memory"); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv7-r/irq.h b/arch/arm/include/armv7-r/irq.h index 09a107a3171da..a31c90ebbb93e 100644 --- a/arch/arm/include/armv7-r/irq.h +++ b/arch/arm/include/armv7-r/irq.h @@ -402,6 +402,19 @@ static inline void up_irq_restore(irqstate_t flags) ); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv8-m/irq.h b/arch/arm/include/armv8-m/irq.h index a440a4da9895b..4e3f3b9b0cd3c 100644 --- a/arch/arm/include/armv8-m/irq.h +++ b/arch/arm/include/armv8-m/irq.h @@ -508,6 +508,19 @@ static inline void setcontrol(uint32_t control) : "memory"); } +static inline_function uint32_t up_getsp(void) +{ + uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv8-r/irq.h b/arch/arm/include/armv8-r/irq.h index e094657485a7c..b0e1a9ff8d767 100644 --- a/arch/arm/include/armv8-r/irq.h +++ b/arch/arm/include/armv8-r/irq.h @@ -402,6 +402,19 @@ static inline void up_irq_restore(irqstate_t flags) ); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/irq.h b/arch/arm/include/irq.h index 21e221816bd55..137592728c371 100644 --- a/arch/arm/include/irq.h +++ b/arch/arm/include/irq.h @@ -66,8 +66,6 @@ * Pre-processor Prototypes ****************************************************************************/ -#define up_getsp() (uintptr_t)__builtin_frame_address(0) - #ifndef __ASSEMBLY__ #ifdef __cplusplus diff --git a/arch/arm/include/spinlock.h b/arch/arm/include/spinlock.h index b9c53d94185f9..519cbae8f9be4 100644 --- a/arch/arm/include/spinlock.h +++ b/arch/arm/include/spinlock.h @@ -59,8 +59,8 @@ * all memory accesses are complete */ -#define SP_DSB(n) __asm__ __volatile__ ("dsb sy" : : : "memory") -#define SP_DMB(n) __asm__ __volatile__ ("dmb st" : : : "memory") +#define SP_DSB() __asm__ __volatile__ ("dsb sy" : : : "memory") +#define SP_DMB() __asm__ __volatile__ ("dmb st" : : : "memory") #ifdef CONFIG_ARM_HAVE_WFE_SEV #define SP_WFE() __asm__ __volatile__ ("wfe" : : : "memory") diff --git a/arch/arm/include/syscall.h b/arch/arm/include/syscall.h index 3b424bbb08a6e..ae59f8be75ae1 100644 --- a/arch/arm/include/syscall.h +++ b/arch/arm/include/syscall.h @@ -136,6 +136,18 @@ static inline uintptr_t sys_call0(unsigned int nbr) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0) + : "memory", "r14", "r0" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); __asm__ __volatile__ @@ -145,6 +157,7 @@ static inline uintptr_t sys_call0(unsigned int nbr) : "i"(SYS_syscall), "r"(reg0) : "memory", "r14" ); +#endif return reg0; } @@ -153,6 +166,20 @@ static inline uintptr_t sys_call0(unsigned int nbr) static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1) + : "memory", "r14", "r0", "r1" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg1 __asm__("r1") = (long)(parm1); @@ -163,6 +190,7 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) : "i"(SYS_syscall), "r"(reg0), "r"(reg1) : "memory", "r14" ); +#endif return reg0; } @@ -172,6 +200,22 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2) { +#ifdef __ghs__ + register long reg0 = (long)nbr; + register long reg2 = (long)parm2; + register long reg1 = (long)parm1; + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) + : "memory", "r14", "r0", "r1", "r2" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg2 __asm__("r2") = (long)(parm2); register long reg1 __asm__("r1") = (long)(parm1); @@ -183,6 +227,7 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) : "memory", "r14" ); +#endif return reg0; } @@ -192,6 +237,24 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3) + : "memory", "r14", "r0", "r1", "r2", "r3" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg3 __asm__("r3") = (long)(parm3); register long reg2 __asm__("r2") = (long)(parm2); @@ -204,6 +267,7 @@ static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3) : "memory", "r14" ); +#endif return reg0; } @@ -214,6 +278,27 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg4 = (long)(parm4); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4) + : "memory", "r14", "r0", "r1", "r2", "r3", "r4" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg4 __asm__("r4") = (long)(parm4); register long reg3 __asm__("r3") = (long)(parm3); @@ -228,6 +313,7 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, "r"(reg3), "r"(reg4) : "memory", "r14" ); +#endif return reg0; } @@ -238,6 +324,29 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg5 = (long)(parm5); + register long reg4 = (long)(parm4); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "mov r5, %7\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5) + : "memory", "r14", "r0", "r1", "r2", "r3", "r4", "r5" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg5 __asm__("r5") = (long)(parm5); register long reg4 __asm__("r4") = (long)(parm4); @@ -253,6 +362,7 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, "r"(reg3), "r"(reg4), "r"(reg5) : "memory", "r14" ); +#endif return reg0; } @@ -264,6 +374,31 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg6 = (long)(parm6); + register long reg5 = (long)(parm5); + register long reg4 = (long)(parm4); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "mov r5, %7\n\t" + "mov r6, %8\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) + : "memory", "r14", "r0", "r1", "r2", "r3", "r4", "r5", "r6" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg6 __asm__("r6") = (long)(parm6); register long reg5 __asm__("r5") = (long)(parm5); @@ -280,6 +415,7 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) : "memory", "r14" ); +#endif return reg0; } @@ -288,6 +424,26 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, static inline long smh_call(unsigned int nbr, void *parm) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg1 = (long)(parm); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" +#if defined(CONFIG_ARCH_ARMV6M) || \ + defined(CONFIG_ARCH_ARMV7M) || \ + defined(CONFIG_ARCH_ARMV8M) + "bkpt %1" +#else + "svc %1" +#endif + : "=r"(reg0) + : "i"(SYS_smhcall), "r"(reg0), "r"(reg1) + : "memory", "r14", "r0", "r1" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg1 __asm__("r1") = (long)(parm); @@ -304,6 +460,7 @@ static inline long smh_call(unsigned int nbr, void *parm) : "i"(SYS_smhcall), "r"(reg0), "r"(reg1) : "memory", "r14" ); +#endif return reg0; } diff --git a/arch/arm/include/tlsr82/irq.h b/arch/arm/include/tlsr82/irq.h index d7032bfbb17ac..edb15a170273c 100644 --- a/arch/arm/include/tlsr82/irq.h +++ b/arch/arm/include/tlsr82/irq.h @@ -236,6 +236,19 @@ static inline uint32_t getcontrol(void) return 0; } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "tmov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/types.h b/arch/arm/include/types.h index eaaac738ddfbd..043937a84b5de 100644 --- a/arch/arm/include/types.h +++ b/arch/arm/include/types.h @@ -81,6 +81,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/arm/src/armv6-m/barriers.h b/arch/arm/src/armv6-m/barriers.h index 20c1a089dbe46..e0b661bc94787 100644 --- a/arch/arm/src/armv6-m/barriers.h +++ b/arch/arm/src/armv6-m/barriers.h @@ -31,12 +31,12 @@ /* ARMv6-M memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") -#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") -#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_dsb() __asm__ __volatile__ ("dsb " : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") +#define arm_dmb() __asm__ __volatile__ ("dmb " : : : "memory") -#define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) -#define ARM_DMB() arm_dmb(15) +#define ARM_DSB() arm_dsb() +#define ARM_ISB() arm_isb() +#define ARM_DMB() arm_dmb() #endif /* __ARCH_ARM_SRC_ARMV6_M_BARRIERS_H */ diff --git a/arch/arm/src/armv7-a/barriers.h b/arch/arm/src/armv7-a/barriers.h index e8b5d94f93ac2..2258e4110f57d 100644 --- a/arch/arm/src/armv7-a/barriers.h +++ b/arch/arm/src/armv7-a/barriers.h @@ -31,15 +31,15 @@ /* ARMv7-A memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") #define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") #define arm_nop() __asm__ __volatile__ ("nop\n") #define arm_sev() __asm__ __volatile__ ("sev\n") #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) #define ARM_DMB() arm_dmb(15) +#define ARM_ISB() arm_isb() #define ARM_NOP() arm_nop() #define ARM_SEV() arm_sev() diff --git a/arch/arm/src/armv7-m/arm_exception.S b/arch/arm/src/armv7-m/arm_exception.S index d2478aadd2b15..4f057ae113ac1 100644 --- a/arch/arm/src/armv7-m/arm_exception.S +++ b/arch/arm/src/armv7-m/arm_exception.S @@ -87,9 +87,12 @@ ****************************************************************************/ .globl exception_common - +#ifdef __ghs__ + .thumb2 +#else .syntax unified .thumb +#endif .file "arm_exception.S" /**************************************************************************** @@ -119,8 +122,12 @@ .text .section .text.exception_common +#ifdef __ghs__ + .type exception_common, $function +#else .thumb_func .type exception_common, function +#endif exception_common: mrs r0, ipsr /* R0=exception number */ diff --git a/arch/arm/src/armv7-m/arm_saveusercontext.S b/arch/arm/src/armv7-m/arm_saveusercontext.S index 58d02f575f9da..5e67be0e6c51b 100644 --- a/arch/arm/src/armv7-m/arm_saveusercontext.S +++ b/arch/arm/src/armv7-m/arm_saveusercontext.S @@ -28,8 +28,12 @@ .file "arm_saveusercontext.S" .text +#ifdef __ghs__ + .thumb2 +#else .syntax unified .thumb +#endif /**************************************************************************** * Public Functions @@ -52,7 +56,11 @@ .globl up_saveusercontext .globl up_saveusercontext +#ifdef __ghs__ + .type up_saveusercontext, $function +#else .type up_saveusercontext, %function +#endif up_saveusercontext: diff --git a/arch/arm/src/armv7-m/barriers.h b/arch/arm/src/armv7-m/barriers.h index b8d91fddacbd4..b020427a620e4 100644 --- a/arch/arm/src/armv7-m/barriers.h +++ b/arch/arm/src/armv7-m/barriers.h @@ -31,12 +31,12 @@ /* ARMv7-M memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") -#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") -#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_dsb() __asm__ __volatile__ ("dsb " : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") +#define arm_dmb() __asm__ __volatile__ ("dmb " : : : "memory") -#define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) -#define ARM_DMB() arm_dmb(15) +#define ARM_DSB() arm_dsb() +#define ARM_ISB() arm_isb() +#define ARM_DMB() arm_dmb() #endif /* __ARCH_ARM_SRC_ARMV7_M_BARRIERS_H */ diff --git a/arch/arm/src/armv7-r/barriers.h b/arch/arm/src/armv7-r/barriers.h index fe17d57db36fb..71005f4a4dff9 100644 --- a/arch/arm/src/armv7-r/barriers.h +++ b/arch/arm/src/armv7-r/barriers.h @@ -31,15 +31,15 @@ /* ARMv7-R memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") #define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") #define arm_nop() __asm__ __volatile__ ("nop\n") #define arm_sev() __asm__ __volatile__ ("sev\n") #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) #define ARM_DMB() arm_dmb(15) +#define ARM_ISB() arm_isb() #define ARM_NOP() arm_nop() #define ARM_SEV() arm_sev() diff --git a/arch/arm/src/armv8-m/arm_hardfault.c b/arch/arm/src/armv8-m/arm_hardfault.c index 83c9e3d5ed1e5..d69c4f599c1f9 100644 --- a/arch/arm/src/armv8-m/arm_hardfault.c +++ b/arch/arm/src/armv8-m/arm_hardfault.c @@ -162,7 +162,7 @@ int arm_hardfault(int irq, void *context, void *arg) hfalert("PANIC!!! Hard Fault!:"); hfalert("\tIRQ: %d regs: %p\n", irq, context); - hfalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08" + hfalert("\tBASEPRI: %08" PRIx8 " PRIMASK: %08" PRIx8 " IPSR: %08" PRIx32 " CONTROL: %08" PRIx32 "\n", getbasepri(), getprimask(), getipsr(), getcontrol()); hfalert("\tCFSR: %08" PRIx32 " HFSR: %08" PRIx32 " DFSR: %08" diff --git a/arch/arm/src/armv8-m/arm_memfault.c b/arch/arm/src/armv8-m/arm_memfault.c index e9bdbc580eb49..685e2657bd845 100644 --- a/arch/arm/src/armv8-m/arm_memfault.c +++ b/arch/arm/src/armv8-m/arm_memfault.c @@ -66,9 +66,9 @@ int arm_memfault(int irq, void *context, void *arg) mfalert("PANIC!!! Memory Management Fault:\n"); mfalert("\tIRQ: %d context: %p\n", irq, context); - mfalert("\tCFSR: %08x MMFAR: %08x\n", + mfalert("\tCFSR: %08" PRIx32 " MMFAR: %08" PRIx32 "\n", getreg32(NVIC_CFAULTS), getreg32(NVIC_MEMMANAGE_ADDR)); - mfalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08" + mfalert("\tBASEPRI: %08" PRIx32 " PRIMASK: %08" PRIx32 " IPSR: %08" PRIx32 " CONTROL: %08" PRIx32 "\n", getbasepri(), getprimask(), getipsr(), getcontrol()); diff --git a/arch/arm/src/armv8-m/arm_securefault.c b/arch/arm/src/armv8-m/arm_securefault.c index fb0f2a4736453..82285196eb0af 100644 --- a/arch/arm/src/armv8-m/arm_securefault.c +++ b/arch/arm/src/armv8-m/arm_securefault.c @@ -66,12 +66,13 @@ int arm_securefault(int irq, void *context, void *arg) sfalert("PANIC!!! Secure Fault:\n"); sfalert("\tIRQ: %d regs: %p\n", irq, context); - sfalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08" + sfalert("\tBASEPRI: %08" PRIx8 " PRIMASK: %08" PRIx8 " IPSR: %08" PRIx32 " CONTROL: %08" PRIx32 "\n", getbasepri(), getprimask(), getipsr(), getcontrol()); - sfalert("\tCFSR: %08x HFSR: %08x DFSR: %08x\n", getreg32(NVIC_CFAULTS), - getreg32(NVIC_HFAULTS), getreg32(NVIC_DFAULTS)); - sfalert("\tBFAR: %08x AFSR: %08x SFAR: %08x\n", + sfalert("\tCFSR: %08" PRIx32 " HFSR: %08" PRIx32 " DFSR: %08" PRIx32 "\n", + getreg32(NVIC_CFAULTS), getreg32(NVIC_HFAULTS), + getreg32(NVIC_DFAULTS)); + sfalert("\tBFAR: %08" PRIx32 " AFSR: %08" PRIx32 " SFAR: %08" PRIx32 "\n", getreg32(NVIC_BFAULT_ADDR), getreg32(NVIC_AFAULTS), getreg32(SAU_SFAR)); diff --git a/arch/arm/src/armv8-m/barriers.h b/arch/arm/src/armv8-m/barriers.h index 789268e567cea..22d896989b789 100644 --- a/arch/arm/src/armv8-m/barriers.h +++ b/arch/arm/src/armv8-m/barriers.h @@ -31,12 +31,12 @@ /* ARMv8-M memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") +#define arm_dmb() __asm__ __volatile__ ("dmb " : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") -#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define ARM_ISB() arm_isb() +#define ARM_DMB() arm_dmb() #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) -#define ARM_DMB() arm_dmb(15) #endif /* __ARCH_ARM_SRC_ARMV8_M_BARRIERS_H */ diff --git a/arch/arm/src/armv8-r/barriers.h b/arch/arm/src/armv8-r/barriers.h index 0fd9f5790ba78..7e542eb99d7a4 100644 --- a/arch/arm/src/armv8-r/barriers.h +++ b/arch/arm/src/armv8-r/barriers.h @@ -31,15 +31,15 @@ /* ARMv8-R memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") #define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") #define arm_nop() __asm__ __volatile__ ("nop\n") #define arm_sev() __asm__ __volatile__ ("sev\n") #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) #define ARM_DMB() arm_dmb(15) +#define ARM_ISB() arm_isb() #define ARM_NOP() arm_nop() #define ARM_SEV() arm_sev() diff --git a/arch/arm/src/common/gnu/fork.S b/arch/arm/src/common/gnu/fork.S index 7697561a2750a..d98003d4dab1e 100644 --- a/arch/arm/src/common/gnu/fork.S +++ b/arch/arm/src/common/gnu/fork.S @@ -26,7 +26,6 @@ #include "arm_fork.h" - .syntax unified .file "fork.S" /**************************************************************************** @@ -78,7 +77,11 @@ ****************************************************************************/ .globl up_fork +#ifdef __ghs__ + .type up_fork, $function +#else .type up_fork, function +#endif up_fork: /* Create a stack frame */ diff --git a/arch/arm/src/rp2040/rp2040_i2c_slave.c b/arch/arm/src/rp2040/rp2040_i2c_slave.c index af9e057dc58d6..c2b1d9f0665f5 100644 --- a/arch/arm/src/rp2040/rp2040_i2c_slave.c +++ b/arch/arm/src/rp2040/rp2040_i2c_slave.c @@ -152,6 +152,7 @@ static int i2c_interrupt(int irq, void *context, void *arg) rp2040_i2c_slave_t *priv = (rp2040_i2c_slave_t *)arg; uint32_t data_cmd; uint32_t state; + int length; state = getreg32(RP2040_I2C_IC_INTR_STAT(priv->controller)); @@ -159,7 +160,8 @@ static int i2c_interrupt(int irq, void *context, void *arg) if (state & RP2040_I2C_IC_INTR_STAT_R_RD_REQ) { - if (priv->tx_buf_ptr < priv->tx_buf_end) + length = priv->tx_buf_end - priv->tx_buf_ptr; + if (length > 0) { while (priv->tx_buf_ptr < priv->tx_buf_end && getreg32(RP2040_I2C_IC_TXFLR(priv->controller)) @@ -168,6 +170,11 @@ static int i2c_interrupt(int irq, void *context, void *arg) putreg32(*priv->tx_buf_ptr++, RP2040_I2C_IC_DATA_CMD(priv->controller)); } + + if (priv->callback != NULL) + { + priv->callback(priv, I2CS_TX_COMPLETE, length); + } } else { @@ -203,7 +210,8 @@ static int i2c_interrupt(int irq, void *context, void *arg) { if (priv->callback != NULL && priv->rx_buf_ptr > priv->rx_buffer) { - priv->callback(priv, priv->rx_buf_ptr - priv->rx_buffer); + priv->callback(priv, I2CS_RX_COMPLETE, + priv->rx_buf_ptr - priv->rx_buffer); priv->rx_buf_ptr = priv->rx_buffer; } @@ -216,7 +224,8 @@ static int i2c_interrupt(int irq, void *context, void *arg) { if (priv->callback != NULL && priv->rx_buf_ptr > priv->rx_buffer) { - priv->callback(priv, priv->rx_buf_ptr - priv->rx_buffer); + priv->callback(priv, I2CS_RX_COMPLETE, + priv->rx_buf_ptr - priv->rx_buffer); priv->rx_buf_ptr = priv->rx_buffer; } diff --git a/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c b/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c index 32792bbb0fc1b..533f97c5855b0 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c +++ b/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c @@ -427,9 +427,19 @@ static int s32k1xx_lpi2c_slave_isr_process( if ((priv->read_bufindex > 0) && (priv->callback != NULL)) { - priv->callback(priv->callback_arg, priv->read_bufindex); + priv->callback(priv->callback_arg, I2CS_RX_COMPLETE, + priv->read_bufindex); priv->read_bufindex = 0; } + + /* Execute the registered callback function if data was send */ + + if ((priv->write_bufindex > 0) && (priv->callback != NULL)) + { + priv->callback(priv->callback_arg, I2CS_TX_COMPLETE, + priv->write_bufindex); + priv->write_bufindex = 0; + } } /* Slave Bit Error (abort current transfer) */ diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig index 91c66280aa2cd..15ba5312c547e 100644 --- a/arch/arm/src/stm32h7/Kconfig +++ b/arch/arm/src/stm32h7/Kconfig @@ -293,6 +293,12 @@ config STM32H7_PWR_DIRECT_SMPS_SUPPLY depends on STM32H7_HAVE_SMPS default n +config STM32H7_PWR_EXTERNAL_SOURCE_SUPPLY + bool "Use external source as power supply" + default n + ---help--- + Select this option for using an external power supply connected directly to the VCAP pin. + choice prompt "STM32 H7 Power Supply Selection" default STM32H7_PWR_DEFAULT_SUPPLY diff --git a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c index da7af1f59c796..51031027aee17 100644 --- a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c +++ b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c @@ -148,12 +148,18 @@ # if defined(CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY) # define STM32_PWR_CR3_SELECTION STM32_PWR_CR3_SDEN +# elif defined(CONFIG_STM32H7_PWR_EXTERNAL_SOURCE_SUPPLY) +# define STM32_PWR_CR3_SELECTION STM32_PWR_CR3_BYPASS # else # define STM32_PWR_CR3_SELECTION STM32_PWR_CR3_LDOEN # endif #else # define STM32_PWR_CR3_MASK 0xffffffff -# define STM32_PWR_CR3_SELECTION (STM32_PWR_CR3_LDOEN | STM32_PWR_CR3_SCUEN) +# if defined(CONFIG_STM32H7_PWR_EXTERNAL_SOURCE_SUPPLY) +# define STM32_PWR_CR3_SELECTION (STM32_PWR_CR3_BYPASS | STM32_PWR_CR3_SCUEN) +# else +# define STM32_PWR_CR3_SELECTION (STM32_PWR_CR3_LDOEN | STM32_PWR_CR3_SCUEN) +# endif #endif diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h index c730a3d4c0743..df9c46636fd94 100644 --- a/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h @@ -276,7 +276,7 @@ #define RCC_PLLCFG_PLLP_SHIFT (17) /* Bit 17-21: Main PLL div factor for PLLPCLK */ #define RCC_PLLCFG_PLLP_MASK (0x1f << RCC_PLLCFG_PLLP_SHIFT) -# define RCC_PLLCFG_PLLP (((n)-1) << RCC_PLLCFG_PLLP_SHIFT) /* 2..32 */ +#define RCC_PLLCFG_PLLP(n) (((n)-1) << RCC_PLLCFG_PLLP_SHIFT) /* 2..32 */ #define RCC_PLLCFG_PLLQEN (1 << 24) /* Bit 24: Main PLL PLLQCLK output enable */ diff --git a/arch/arm64/include/spinlock.h b/arch/arm64/include/spinlock.h index 5eee94bb55c39..ced899e13b559 100644 --- a/arch/arm64/include/spinlock.h +++ b/arch/arm64/include/spinlock.h @@ -59,8 +59,8 @@ * all memory accesses are complete */ -#define SP_DSB(n) __asm__ __volatile__ ("dsb sy" : : : "memory") -#define SP_DMB(n) __asm__ __volatile__ ("dmb st" : : : "memory") +#define SP_DSB() __asm__ __volatile__ ("dsb sy" : : : "memory") +#define SP_DMB() __asm__ __volatile__ ("dmb st" : : : "memory") #define SP_WFE() __asm__ __volatile__ ("wfe" : : : "memory") #define SP_SEV() __asm__ __volatile__ ("sev" : : : "memory") diff --git a/arch/arm64/include/types.h b/arch/arm64/include/types.h index 5d783496736af..a0faaa28ca055 100644 --- a/arch/arm64/include/types.h +++ b/arch/arm64/include/types.h @@ -72,6 +72,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + #if defined(__SIZE_TYPE__) /* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. * We simply change "unsigned" to "signed" for this single definition diff --git a/arch/avr/include/avr/types.h b/arch/avr/include/avr/types.h index 6dedd3df05f8e..2d11975a77e1e 100644 --- a/arch/avr/include/avr/types.h +++ b/arch/avr/include/avr/types.h @@ -73,6 +73,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A (near) size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/avr/include/avr32/types.h b/arch/avr/include/avr32/types.h index ad3be5ba959bc..a763ccba301ef 100644 --- a/arch/avr/include/avr32/types.h +++ b/arch/avr/include/avr32/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/ceva/include/spinlock.h b/arch/ceva/include/spinlock.h index 13cc8fb1b29ff..de125f07bd53d 100644 --- a/arch/ceva/include/spinlock.h +++ b/arch/ceva/include/spinlock.h @@ -61,8 +61,8 @@ * */ -#define SP_DSB(n) up_dsb() -#define SP_DMB(n) up_dmb() +#define SP_DSB() up_dsb() +#define SP_DMB() up_dmb() /**************************************************************************** * Public Types diff --git a/arch/hc/include/hc12/types.h b/arch/hc/include/hc12/types.h index 2a85a1a755fa3..62b5c0beb7b00 100644 --- a/arch/hc/include/hc12/types.h +++ b/arch/hc/include/hc12/types.h @@ -79,6 +79,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is two bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/hc/include/hcs12/types.h b/arch/hc/include/hcs12/types.h index 28e52459b3f9c..9dbf3d93f0277 100644 --- a/arch/hc/include/hcs12/types.h +++ b/arch/hc/include/hcs12/types.h @@ -80,6 +80,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is two bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/mips/include/types.h b/arch/mips/include/types.h index de4870bbed93b..d08f07e0994df 100644 --- a/arch/mips/include/types.h +++ b/arch/mips/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/misoc/include/types.h b/arch/misoc/include/types.h index a6d27b03ac714..1a14ab6025fd1 100644 --- a/arch/misoc/include/types.h +++ b/arch/misoc/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/or1k/include/types.h b/arch/or1k/include/types.h index 30a76756ed308..3a4ad630e0e90 100644 --- a/arch/or1k/include/types.h +++ b/arch/or1k/include/types.h @@ -73,6 +73,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/renesas/include/m16c/types.h b/arch/renesas/include/m16c/types.h index 3b2f720015ba2..3f2947aab6477 100644 --- a/arch/renesas/include/m16c/types.h +++ b/arch/renesas/include/m16c/types.h @@ -72,6 +72,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/renesas/include/rx65n/types.h b/arch/renesas/include/rx65n/types.h index d71395d52d1c0..fb73d2400ff45 100644 --- a/arch/renesas/include/rx65n/types.h +++ b/arch/renesas/include/rx65n/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/renesas/include/sh1/types.h b/arch/renesas/include/sh1/types.h index 36c2f2bbcd299..497dc0360d289 100644 --- a/arch/renesas/include/sh1/types.h +++ b/arch/renesas/include/sh1/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 3f04a4738ae89..2da3665d0cc03 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -451,6 +451,20 @@ config ARCH_RV_MMIO_BITS default 32 if ARCH_RV32 default 64 if ARCH_RV64 +config ARCH_RV_HARTID_BASE + int "Base hartid of this cluster" + default 0 + ---help--- + Some RV chips have multiple cluster of harts with + globally numbered mhartids, like qemu-rv, mpfs and + jh7110 etc. Clusters with SMP ability can be managed + by NuttX. As NuttX expects cluster-local hart ids, + we can shift mhartid by this value to derive such + local ids. The SMP_NCPUS still defines number of + harts in the cluster. Note that we assume that global + ids for each cluster are continuous. Note that there + are chips like k230 which don't have global mhartid. + config ARCH_FAMILY string default "rv32" if ARCH_RV32 diff --git a/arch/risc-v/include/spinlock.h b/arch/risc-v/include/spinlock.h index 427e1ef51fdeb..3bfe430338fcf 100644 --- a/arch/risc-v/include/spinlock.h +++ b/arch/risc-v/include/spinlock.h @@ -59,8 +59,8 @@ * */ -#define SP_DSB(n) __asm__ __volatile__ ("fence") -#define SP_DMB(n) __asm__ __volatile__ ("fence") +#define SP_DSB() __asm__ __volatile__ ("fence") +#define SP_DMB() __asm__ __volatile__ ("fence") /**************************************************************************** * Public Types diff --git a/arch/risc-v/include/syscall.h b/arch/risc-v/include/syscall.h index 9d22006760810..ed49fa5c2f6d7 100644 --- a/arch/risc-v/include/syscall.h +++ b/arch/risc-v/include/syscall.h @@ -139,7 +139,8 @@ extern "C" long smh_call(unsigned int nbr, void *parm); -#if defined(CONFIG_ARCH_USE_S_MODE) && defined(__KERNEL__) +#if defined(__KERNEL__) + uintptr_t sys_call0(unsigned int nbr); uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1); uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2); diff --git a/arch/risc-v/include/types.h b/arch/risc-v/include/types.h index 29fe8d56a62c4..9183cf78fa4b4 100644 --- a/arch/risc-v/include/types.h +++ b/arch/risc-v/include/types.h @@ -78,6 +78,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* Use uintreg_t for register-width integers */ #ifdef CONFIG_ARCH_RV32 diff --git a/arch/risc-v/src/common/CMakeLists.txt b/arch/risc-v/src/common/CMakeLists.txt index b1dd33db88710..74b270e4c52a5 100644 --- a/arch/risc-v/src/common/CMakeLists.txt +++ b/arch/risc-v/src/common/CMakeLists.txt @@ -33,6 +33,7 @@ list(APPEND SRCS riscv_releasestack.c riscv_schedulesigaction.c riscv_sigdeliver.c) list(APPEND SRCS riscv_stackframe.c riscv_tcbinfo.c riscv_swint.c) list(APPEND SRCS riscv_switchcontext.c riscv_usestack.c) +list(APPEND SRCS riscv_syscall.S riscv_perform_syscall.c) if(NOT CONFIG_ALARM_ARCH) if(NOT CONFIG_TIMER_ARCH) @@ -122,7 +123,7 @@ if(CONFIG_RISCV_PERCPU_SCRATCH) endif() if(CONFIG_ARCH_USE_S_MODE) - add_subdirectory(supervisor) + list(APPEND SRCS riscv_sbi.c) endif() target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/risc-v/src/common/Make.defs b/arch/risc-v/src/common/Make.defs index e3c46f6fcaa0b..bcd03e269249a 100644 --- a/arch/risc-v/src/common/Make.defs +++ b/arch/risc-v/src/common/Make.defs @@ -25,6 +25,7 @@ endif # Specify our general Assembly files CMN_ASRCS += riscv_vectors.S riscv_exception_common.S riscv_mhartid.S CMN_ASRCS += riscv_saveusercontext.S +CMN_ASRCS += riscv_syscall.S # Specify C code within the common directory to be included CMN_CSRCS += riscv_initialize.c riscv_swint.c riscv_mtimer.c @@ -35,6 +36,7 @@ CMN_CSRCS += riscv_idle.c riscv_modifyreg32.c riscv_nputs.c riscv_releasestack.c CMN_CSRCS += riscv_registerdump.c riscv_stackframe.c riscv_schedulesigaction.c CMN_CSRCS += riscv_sigdeliver.c riscv_switchcontext.c CMN_CSRCS += riscv_usestack.c riscv_tcbinfo.c +CMN_CSRCS += riscv_perform_syscall.c ifneq ($(CONFIG_ALARM_ARCH),y) ifneq ($(CONFIG_TIMER_ARCH),y) @@ -121,8 +123,6 @@ ifeq ($(CONFIG_RISCV_PERCPU_SCRATCH),y) CMN_CSRCS += riscv_percpu.c endif -# Kernel runs in supervisor mode or machine mode ? - ifeq ($(CONFIG_ARCH_USE_S_MODE),y) -include common/supervisor/Make.defs +CMN_CSRCS += riscv_sbi.c endif diff --git a/arch/risc-v/src/common/fork.S b/arch/risc-v/src/common/fork.S index 9134266feca0a..a7ca257f05998 100644 --- a/arch/risc-v/src/common/fork.S +++ b/arch/risc-v/src/common/fork.S @@ -123,6 +123,10 @@ up_fork: REGSTORE s0, FORK_S0_OFFSET(sp) #endif +#ifdef RISCV_SAVE_GP + REGSTORE gp, FORK_GP_OFFSET(sp) +#endif + addi a0, sp, FORK_SIZEOF REGSTORE a0, FORK_SP_OFFSET(sp) /* original SP */ REGSTORE x1, FORK_RA_OFFSET(sp) /* return address */ diff --git a/arch/risc-v/src/common/riscv_exception.c b/arch/risc-v/src/common/riscv_exception.c index cefa6c03f99ff..6c296f67ef8df 100644 --- a/arch/risc-v/src/common/riscv_exception.c +++ b/arch/risc-v/src/common/riscv_exception.c @@ -287,12 +287,7 @@ void riscv_exception_attach(void) irq_attach(RISCV_IRQ_ECALLS, riscv_exception, NULL); irq_attach(RISCV_IRQ_ECALLH, riscv_exception, NULL); - -#ifndef CONFIG_ARCH_USE_S_MODE - irq_attach(RISCV_IRQ_ECALLM, riscv_swint, NULL); -#else irq_attach(RISCV_IRQ_ECALLM, riscv_exception, NULL); -#endif irq_attach(RISCV_IRQ_INSTRUCTIONPF, riscv_exception, NULL); @@ -309,6 +304,6 @@ void riscv_exception_attach(void) #ifdef CONFIG_SMP irq_attach(RISCV_IRQ_SOFT, riscv_pause_handler, NULL); #else - irq_attach(RISCV_IRQ_MSOFT, riscv_exception, NULL); + irq_attach(RISCV_IRQ_SOFT, riscv_exception, NULL); #endif } diff --git a/arch/risc-v/src/common/riscv_fork.c b/arch/risc-v/src/common/riscv_fork.c index 9187cc6ab5ef7..40e463b2aef7c 100644 --- a/arch/risc-v/src/common/riscv_fork.c +++ b/arch/risc-v/src/common/riscv_fork.c @@ -308,7 +308,7 @@ pid_t riscv_fork(const struct fork_s *context) #endif child->cmn.xcp.regs[REG_SP] = newsp; /* Stack pointer */ #ifdef RISCV_SAVE_GP - child->cmn.xcp.regs[REG_GP] = newsp; /* Global pointer */ + child->cmn.xcp.regs[REG_GP] = context->gp; /* Global pointer */ #endif #ifdef CONFIG_ARCH_FPU fregs = riscv_fpuregs(&child->cmn); diff --git a/arch/risc-v/src/common/riscv_fork.h b/arch/risc-v/src/common/riscv_fork.h index 26a2ec5925d8c..bfb2560f1faa0 100644 --- a/arch/risc-v/src/common/riscv_fork.h +++ b/arch/risc-v/src/common/riscv_fork.h @@ -119,6 +119,11 @@ struct fork_s { /* CPU registers */ +#ifdef CONFIG_RISCV_FRAMEPOINTER + uintreg_t fp; /* Frame pointer */ +#else + uintreg_t s0; /* Saved register s0 */ +#endif uintreg_t s1; /* Saved register s1 */ uintreg_t s2; /* Saved register s2 */ uintreg_t s3; /* Saved register s3 */ @@ -130,11 +135,6 @@ struct fork_s uintreg_t s9; /* Saved register s9 */ uintreg_t s10; /* Saved register s10 */ uintreg_t s11; /* Saved register s11 */ -#ifdef CONFIG_RISCV_FRAMEPOINTER - uintreg_t fp; /* Frame pointer */ -#else - uintreg_t s0; /* Saved register s0 */ -#endif uintreg_t sp; /* Stack pointer */ uintreg_t ra; /* Return address */ #ifdef RISCV_SAVE_GP diff --git a/arch/risc-v/src/common/riscv_macros.S b/arch/risc-v/src/common/riscv_macros.S index 0ab8358d507d9..03ddfe872d8ed 100644 --- a/arch/risc-v/src/common/riscv_macros.S +++ b/arch/risc-v/src/common/riscv_macros.S @@ -362,6 +362,9 @@ REGLOAD \out, RISCV_PERCPU_HARTID(\out) #else csrr \out, CSR_MHARTID +# if CONFIG_ARCH_RV_HARTID_BASE > 0 + add \out, \out, - CONFIG_ARCH_RV_HARTID_BASE +# endif #endif .endm diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c b/arch/risc-v/src/common/riscv_perform_syscall.c similarity index 97% rename from arch/risc-v/src/common/supervisor/riscv_perform_syscall.c rename to arch/risc-v/src/common/riscv_perform_syscall.c index cd134fb4e1b07..c687ebdec4923 100644 --- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c +++ b/arch/risc-v/src/common/riscv_perform_syscall.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/supervisor/riscv_perform_syscall.c + * arch/risc-v/src/common/riscv_perform_syscall.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/arch/risc-v/src/common/supervisor/riscv_sbi.c b/arch/risc-v/src/common/riscv_sbi.c similarity index 98% rename from arch/risc-v/src/common/supervisor/riscv_sbi.c rename to arch/risc-v/src/common/riscv_sbi.c index 626e2d068ff13..4eff3c167c012 100644 --- a/arch/risc-v/src/common/supervisor/riscv_sbi.c +++ b/arch/risc-v/src/common/riscv_sbi.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/supervisor/riscv_sbi.c + * arch/risc-v/src/common/riscv_sbi.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/arch/risc-v/src/common/supervisor/riscv_syscall.S b/arch/risc-v/src/common/riscv_syscall.S similarity index 98% rename from arch/risc-v/src/common/supervisor/riscv_syscall.S rename to arch/risc-v/src/common/riscv_syscall.S index bda64d3de2cfb..802037ed3b675 100644 --- a/arch/risc-v/src/common/supervisor/riscv_syscall.S +++ b/arch/risc-v/src/common/riscv_syscall.S @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/supervisor/riscv_syscall.S + * arch/risc-v/src/common/riscv_syscall.S * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/arch/risc-v/src/common/supervisor/Make.defs b/arch/risc-v/src/common/supervisor/Make.defs deleted file mode 100644 index 65375a3f0979a..0000000000000 --- a/arch/risc-v/src/common/supervisor/Make.defs +++ /dev/null @@ -1,28 +0,0 @@ -############################################################################ -# arch/risc-v/src/common/supervisor/Make.defs -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. The -# ASF licenses this file to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance with the -# License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -############################################################################ - -# If the NuttX kernel runs in S-mode - -CMN_ASRCS += riscv_syscall.S -CMN_CSRCS += riscv_perform_syscall.c -CMN_CSRCS += riscv_sbi.c - -INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)common$(DELIM)supervisor -VPATH += common$(DELIM)supervisor diff --git a/arch/risc-v/src/qemu-rv/CMakeLists.txt b/arch/risc-v/src/qemu-rv/CMakeLists.txt index 397069bae8c31..a666c4ad0dbfd 100644 --- a/arch/risc-v/src/qemu-rv/CMakeLists.txt +++ b/arch/risc-v/src/qemu-rv/CMakeLists.txt @@ -39,4 +39,8 @@ if(CONFIG_MM_PGALLOC) list(APPEND SRCS qemu_rv_pgalloc.c) endif() +if(CONFIG_BUILD_PROTECTED) + list(APPEND SRCS qemu_rv_userspace.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/risc-v/src/qemu-rv/Kconfig b/arch/risc-v/src/qemu-rv/Kconfig index 5d5b8b2dd41ec..550b854c57953 100644 --- a/arch/risc-v/src/qemu-rv/Kconfig +++ b/arch/risc-v/src/qemu-rv/Kconfig @@ -40,4 +40,24 @@ config ARCH_CHIP_QEMU_RV_ISA_V default n select ARCH_RV_ISA_V -endif +config ARCH_CHIP_QEMU_RV_CLUSTER + bool "Enable cluster support" + default n + +if ARCH_CHIP_QEMU_RV_CLUSTER + +config ARCH_CHIP_QEMU_RV_PLIC + hex "Base address of PLIC device" + default 0xc000000 + +config ARCH_CHIP_QEMU_RV_CLINT + hex "Base address of CLINT device" + default 0x2000000 + +config ARCH_CHIP_QEMU_RV_ACLINT + hex "Base address of ACLINT device" + default 0x2f00000 + +endif # ARCH_CHIP_QEMU_RV_CLUSTER + +endif # ARCH_CHIP_QEMU_RV diff --git a/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h b/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h index 420cefefe9f54..a2c372f08fbcd 100644 --- a/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h +++ b/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h @@ -27,11 +27,25 @@ /* Register Base Address ****************************************************/ -#define QEMU_RV_CLINT_BASE 0x02000000 -#define QEMU_RV_ACLINT_BASE 0x02f00000 -#define QEMU_RV_PLIC_BASE 0x0c000000 +#ifdef CONFIG_ARCH_CHIP_QEMU_RV_PLIC +# define QEMU_RV_PLIC_BASE CONFIG_ARCH_CHIP_QEMU_RV_PLIC +#else +# define QEMU_RV_PLIC_BASE 0xc000000 +#endif + +#ifdef CONFIG_ARCH_CHIP_QEMU_RV_CLINT +# define QEMU_RV_CLINT_BASE CONFIG_ARCH_CHIP_QEMU_RV_CLINT +#else +# define QEMU_RV_CLINT_BASE 0x2000000 +#endif + +#ifdef CONFIG_ARCH_CHIP_QEMU_RV_ACLINT +# define QEMU_RV_ACLINT_BASE CONFIG_ARCH_CHIP_QEMU_RV_ACLINT +#else +# define QEMU_RV_ACLINT_BASE 0x2f00000 +#endif -#define QEMU_RV_RESET_BASE 0x100000 +#define QEMU_RV_RESET_BASE 0x100000 #ifdef CONFIG_ARCH_USE_S_MODE # define QEMU_RV_APLIC_BASE 0x0d000000 diff --git a/arch/risc-v/src/rv32m1/rv32m1_head.S b/arch/risc-v/src/rv32m1/rv32m1_head.S index 879936103e89d..0b77171878744 100644 --- a/arch/risc-v/src/rv32m1/rv32m1_head.S +++ b/arch/risc-v/src/rv32m1/rv32m1_head.S @@ -34,6 +34,7 @@ /* Exported Symbols */ .global exception_common + .global return_from_exception .global __start .section .text @@ -155,6 +156,8 @@ exception_common: jal x1, rv32m1_dispatch_irq +return_from_exception: + /* If context switch is needed, return a new sp */ mv sp, a0 diff --git a/arch/sim/CMakeLists.txt b/arch/sim/CMakeLists.txt index 8aa73382d75b1..ded850e13a593 100644 --- a/arch/sim/CMakeLists.txt +++ b/arch/sim/CMakeLists.txt @@ -50,6 +50,11 @@ if(NOT WIN32) TARGET nuttx APPEND PROPERTY NUTTX_COMPILE_OPTIONS -fno-common) +else() + set_property( + TARGET nuttx + APPEND + PROPERTY NUTTX_COMPILE_OPTIONS /std:c11 /experimental:c11atomics) endif() if(CONFIG_SIM_SANITIZE) diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 115104cb89725..5f89953d28716 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -408,11 +408,11 @@ config SIM_FBWIDTH config SIM_FBBPP int "Pixel depth in bits" - default 8 + default 32 ---help--- Pixel depth in bits. Valid choices are 4, 8, 16, 24, or 32. If you use the X11 display emulation, the selected BPP must match the BPP - of your graphics hardware (probably 32 bits). Default: 8 + of your graphics hardware (probably 32 bits). Default: 32 config SIM_FRAMEBUFFER_COUNT int "Framebuffer count" diff --git a/arch/sim/include/types.h b/arch/sim/include/types.h index d347751567940..5e6083b753a95 100644 --- a/arch/sim/include/types.h +++ b/arch/sim/include/types.h @@ -94,6 +94,18 @@ typedef unsigned short _wchar_t; typedef int _wchar_t; #endif +#ifdef _MSC_VER +typedef unsigned short _wint_t; +#else +typedef int _wint_t; +#endif + +#ifdef _MSC_VER +typedef unsigned short _wctype_t; +#else +typedef int _wctype_t; +#endif + #if defined(__SIZE_TYPE__) /* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. * We simply change "unsigned" to "signed" for this single definition diff --git a/arch/sim/src/cmake/Toolchain.cmake b/arch/sim/src/cmake/Toolchain.cmake index c787a9fe3076f..44533362e6c52 100644 --- a/arch/sim/src/cmake/Toolchain.cmake +++ b/arch/sim/src/cmake/Toolchain.cmake @@ -75,15 +75,18 @@ endif() if(CONFIG_SIM_ASAN) add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) add_compile_options(-fsanitize-address-use-after-scope) add_compile_options(-fsanitize=pointer-compare) add_compile_options(-fsanitize=pointer-subtract) + add_link_options(-fsanitize=address) elseif(CONFIG_MM_KASAN_ALL) add_compile_options(-fsanitize=kernel-address) endif() if(CONFIG_SIM_UBSAN) add_compile_options(-fsanitize=undefined) + add_link_options(-fsanitize=undefined) else() if(CONFIG_MM_UBSAN_ALL) add_compile_options(${CONFIG_MM_UBSAN_OPTION}) @@ -95,7 +98,11 @@ else() endif() if(CONFIG_DEBUG_OPT_UNUSED_SECTIONS) - add_link_options(-Wl,--gc-sections) + if(APPLE) + add_link_options(-Wl,-dead_strip) + else() + add_link_options(-Wl,--gc-sections) + endif() add_compile_options(-ffunction-sections -fdata-sections) endif() diff --git a/arch/sim/src/sim/win/sim_hostmemory.c b/arch/sim/src/sim/win/sim_hostmemory.c index 3eaafa0006265..98844efdabdeb 100644 --- a/arch/sim/src/sim/win/sim_hostmemory.c +++ b/arch/sim/src/sim/win/sim_hostmemory.c @@ -24,6 +24,8 @@ #include +#include "sim_internal.h" + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/arch/sparc/include/types.h b/arch/sparc/include/types.h index 51555a9474f73..2da78227b7b90 100644 --- a/arch/sparc/include/types.h +++ b/arch/sparc/include/types.h @@ -72,6 +72,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/tricore/include/types.h b/arch/tricore/include/types.h index 0daba0000627e..0158e7e104190 100644 --- a/arch/tricore/include/types.h +++ b/arch/tricore/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/x86/include/i486/types.h b/arch/x86/include/i486/types.h index 970cdda70d79f..d72d2834863ab 100644 --- a/arch/x86/include/i486/types.h +++ b/arch/x86/include/i486/types.h @@ -71,6 +71,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/x86_64/include/intel64/types.h b/arch/x86_64/include/intel64/types.h index 8880aa37e0de1..f87167174ca70 100644 --- a/arch/x86_64/include/intel64/types.h +++ b/arch/x86_64/include/intel64/types.h @@ -71,6 +71,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + #if defined(__SIZE_TYPE__) /* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. * We simply change "unsigned" to "signed" for this single definition diff --git a/arch/x86_64/include/spinlock.h b/arch/x86_64/include/spinlock.h index ac5b7d8b4f500..d315a32daf9b5 100644 --- a/arch/x86_64/include/spinlock.h +++ b/arch/x86_64/include/spinlock.h @@ -55,8 +55,8 @@ * */ -#define SP_DSB(n) __asm__ __volatile__ ("mfence") -#define SP_DMB(n) __asm__ __volatile__ ("mfence") +#define SP_DSB() __asm__ __volatile__ ("mfence") +#define SP_DMB() __asm__ __volatile__ ("mfence") /**************************************************************************** * Public Types diff --git a/arch/xtensa/include/types.h b/arch/xtensa/include/types.h index 200b46e043f05..2fc02b5b621eb 100644 --- a/arch/xtensa/include/types.h +++ b/arch/xtensa/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/xtensa/src/esp32/esp32_emac.c b/arch/xtensa/src/esp32/esp32_emac.c index 8734c9ff5871c..292d5068d6d59 100644 --- a/arch/xtensa/src/esp32/esp32_emac.c +++ b/arch/xtensa/src/esp32/esp32_emac.c @@ -233,6 +233,7 @@ struct esp32_emac_s ****************************************************************************/ static struct esp32_emac_s s_esp32_emac; +static mutex_t g_lock = NXMUTEX_INITIALIZER; /**************************************************************************** * Private Function Prototypes @@ -564,7 +565,7 @@ static int emac_config(void) /* Hardware reset PHY chip */ esp32_gpiowrite(EMAC_PHYRST_PIN, false); - nxsig_usleep(50); + up_udelay(50); esp32_gpiowrite(EMAC_PHYRST_PIN, true); #endif @@ -597,7 +598,7 @@ static int emac_config(void) break; } - nxsig_usleep(10); + up_udelay(10); } if (i >= EMAC_RESET_TO) @@ -942,7 +943,7 @@ static int emac_read_phy(uint16_t dev_addr, for (i = 0; i < EMAC_READPHY_TO; i++) { - nxsig_usleep(100); + up_udelay(100); val = emac_get_reg(EMAC_MAR_OFFSET); if (!(val & EMAC_PIB)) @@ -1004,7 +1005,7 @@ static int emac_write_phy(uint16_t dev_addr, for (i = 0; i < EMAC_WRITEPHY_TO; i++) { - nxsig_usleep(100); + up_udelay(100); val = emac_get_reg(EMAC_MAR_OFFSET); if (!(val & EMAC_PIB)) @@ -1047,7 +1048,7 @@ static int emac_wait_linkup(struct esp32_emac_s *priv) for (i = 0; i < EMAC_WAITLINK_TO; i++) { - nxsig_usleep(10); + up_udelay(10); ret = emac_read_phy(EMAC_PHY_ADDR, MII_MSR, &val); if (ret != 0) @@ -1184,7 +1185,7 @@ static int emac_init_phy(struct esp32_emac_s *priv) for (i = 0; i < EMAC_RSTPHY_TO; i++) { - nxsig_usleep(100); + up_udelay(100); ret = emac_read_phy(EMAC_PHY_ADDR, MII_MCR, &val); if (ret != 0) @@ -1947,11 +1948,16 @@ static int emac_rmmac(struct net_driver_s *dev, const uint8_t *mac) #ifdef CONFIG_NETDEV_IOCTL static int emac_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { -#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) - struct esp32_emacmac_s *priv = NET2PRIV(dev); -#endif int ret; + /* Get exclusive access to the device structures */ + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + switch (cmd) { #ifdef CONFIG_NETDEV_PHY_IOCTL @@ -2003,6 +2009,7 @@ static int emac_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) break; } + nxmutex_unlock(&g_lock); return ret; } #endif /* CONFIG_NETDEV_IOCTL */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.c b/arch/xtensa/src/esp32s3/esp32s3_rtc.c index dd68de426344d..c01623612bcb8 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.c +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.c @@ -100,6 +100,10 @@ #define RETRY_CAL_EXT 1 +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_160M_FREQ_MHZ (160) +#define CLK_LL_PLL_240M_FREQ_MHZ (240) + /* Lower threshold for a reasonably-looking calibration value for a 32k XTAL. * The ideal value (assuming 32768 Hz frequency) * is 1000000/32768*(2**19) = 16*10^6. @@ -138,6 +142,10 @@ #define RTC_CNTL_PD_CUR_MONITOR_DEFAULT (1) #define RTC_CNTL_PD_CUR_MONITOR_ON (0) +/* Set LDO slave during CPU switch */ + +#define DEFAULT_LDO_SLAVE 0x7 + /* Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP, * RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values. * Valid if RTC_CNTL_DBG_ATTEN is 0. @@ -353,6 +361,8 @@ static RTC_DATA_ATTR struct esp32s3_rtc_backup_s rtc_saved_data; static struct esp32s3_rtc_backup_s *g_rtc_save; static bool g_rt_timer_enabled = false; +static uint32_t g_dig_dbias_pvt_240m = 28; +static uint32_t g_rtc_dbias_pvt_240m = 28; static uint32_t g_dig_dbias_pvt_non_240m = 27; static uint32_t g_rtc_dbias_pvt_non_240m = 27; @@ -377,17 +387,15 @@ static void esp32s3_rtc_clk_32k_enable(bool enable); static void IRAM_ATTR esp32s3_rtc_clk_8m_enable(bool clk_8m_en, bool d256_en); static void esp32s3_rtc_calibrate_ocode(void); -static void IRAM_ATTR esp32s3_rtc_clk_bbpll_disable(void); +static void IRAM_ATTR esp32s3_rtc_bbpll_disable(void); +static void IRAM_ATTR esp32s3_rtc_bbpll_enable(void); static void IRAM_ATTR esp32s3_rtc_bbpll_configure( enum esp32s3_rtc_xtal_freq_e xtal_freq, int pll_freq); static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_8m(void); static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_pll_mhz( int cpu_freq_mhz); - -void IRAM_ATTR esp32s3_rtc_bbpll_disable(void); void esp32s3_rtc_clk_apb_freq_update(uint32_t apb_freq); void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div); -static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles); uint32_t esp32s3_rtc_clk_apb_freq_get(void); #ifdef CONFIG_RTC_ALARM @@ -650,23 +658,6 @@ static uint32_t IRAM_ATTR esp32s3_rtc_clk_cal_internal( return cal_val; } -static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles) -{ - int slow_clk_freq = esp32s3_rtc_clk_slow_freq_get(); - int cal_clk = RTC_CAL_RTC_MUX; - - if (slow_clk_freq == RTC_SLOW_FREQ_32K_XTAL) - { - cal_clk = RTC_CAL_32K_XTAL; - } - else if (slow_clk_freq == RTC_SLOW_FREQ_8MD256) - { - cal_clk = RTC_CAL_8MD256; - } - - esp32s3_rtc_clk_cal(cal_clk, rtc_cycles); -} - /**************************************************************************** * Name: esp32s3_rtc_update_to_xtal * @@ -684,21 +675,13 @@ static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles) void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div) { - ets_update_cpu_frequency(freq); - - /* Set digital voltage for different cpu freq from xtal */ - - if (freq <= 2) - { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_2M); - } - else + struct esp32s3_cpu_freq_config_s cur_config = { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, - DIG_DBIAS_XTAL); - } + 0 + }; - esp32s3_wait_dig_dbias_valid(2); + esp32s3_rtc_clk_cpu_freq_get_config(&cur_config); + ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. * Need to set divider to 1 (reg. value 0) first. @@ -715,6 +698,17 @@ void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div) SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); esp32s3_rtc_clk_apb_freq_update(freq * MHZ); + + if (cur_config.freq_mhz == 240) + { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); + esp_rom_delay_us(40); + } + + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE); } /**************************************************************************** @@ -932,26 +926,16 @@ static void esp32s3_select_rtc_slow_clk(enum esp32s3_slow_clk_sel_e slow_clk) static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_8m(void) { - int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, - SYSTEM_SOC_CLK_SEL); - int origin_div_cnt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, - SYSTEM_PRE_DIV_CNT); - ets_update_cpu_frequency(8); - - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, - DIG_DBIAS_XTAL); - esp32s3_wait_dig_dbias_valid(2); - - if ((DPORT_SOC_CLK_SEL_XTAL == origin_soc_clk) - && (origin_div_cnt > 4)) - { - esp32s3_wait_dig_dbias_valid(2); - } - + ets_update_cpu_frequency(20); REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, - DPORT_SOC_CLK_SEL_8M); + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 2); esp32s3_rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_APPROX); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, + DEFAULT_LDO_SLAVE); } /**************************************************************************** @@ -971,46 +955,85 @@ static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_8m(void) static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_pll_mhz( int cpu_freq_mhz) { - int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, - SYSTEM_SOC_CLK_SEL); - int origin_cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, - SYSTEM_CPUPERIOD_SEL); - int dbias = DIG_DBIAS_80M_160M; - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) - { - /* Nothing to do */ - } - else if (cpu_freq_mhz == 160) - { - dbias = DIG_DBIAS_80M_160M; - per_conf = DPORT_CPUPERIOD_SEL_160; - } - else if (cpu_freq_mhz == 240) + /* There are totally 6 LDO slaves(all on by default). At the moment of + * swithing LDO slave, LDO voltage will also change instantaneously. + * LDO slave can reduce the voltage change caused by switching frequency. + * CPU frequency <= 40M : just open 3 LDO slaves; CPU frequency = 80M : + * open 4 LDO slaves; CPU frequency = 160M : open 5 LDO slaves; + * CPU frequency = 240M : open 6 LDO slaves; LDO voltage will decrease + * at the moment of switching from low frequency to high frequency; + * otherwise, LDO voltage will increase.In order to reduce LDO voltage + * drop, LDO voltage should rise first then fall. + */ + + int pd_slave = cpu_freq_mhz / 80; + struct esp32s3_cpu_freq_config_s cur_config = { - dbias = DIG_DBIAS_240M; - per_conf = DPORT_CPUPERIOD_SEL_240; - } - else + 0 + }; + + esp32s3_rtc_clk_cpu_freq_get_config(&cur_config); + + /* cpu_frequency < 240M: dbias = pvt-dig + 2; + * cpu_frequency = 240M: dbias = pvt-dig + 3; + */ + + if (cpu_freq_mhz > cur_config.freq_mhz) { - rtcerr("Invalid frequency\n"); + if (cpu_freq_mhz == 240) + { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_240m); + esp_rom_delay_us(40); + } + + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, + DEFAULT_LDO_SLAVE >> pd_slave); } - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, dbias); - if ((origin_soc_clk == DPORT_SOC_CLK_SEL_XTAL) - || (origin_soc_clk == DPORT_SOC_CLK_SEL_8M) - || (((origin_soc_clk == DPORT_SOC_CLK_SEL_PLL) - && (0 == origin_cpuperiod_sel)))) + switch (cpu_freq_mhz) { - esp32s3_wait_dig_dbias_valid(2); + case CLK_LL_PLL_80M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0); + break; + + case CLK_LL_PLL_160M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 1); + break; + + case CLK_LL_PLL_240M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 2); + break; + + default: + DEBUGASSERT(0); } - REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); + + /* switch clock source */ + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); esp32s3_rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); + + if (cpu_freq_mhz < cur_config.freq_mhz) + { + if (cur_config.freq_mhz == 240) + { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); + esp_rom_delay_us(40); + } + + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, + DEFAULT_LDO_SLAVE >> pd_slave); + } } #ifdef CONFIG_RTC_ALARM @@ -1080,7 +1103,10 @@ static void esp32s3_rtc_calibrate_ocode(void) bool bg_odone_flag = 0; uint64_t cycle1 = 0; uint64_t max_delay_time_us = 10000; - struct esp32s3_cpu_freq_config_s freq_config; + struct esp32s3_cpu_freq_config_s freq_config = + { + 0 + }; /* Bandgap output voltage is not precise when calibrate o-code by hardware * sometimes, so need software o-code calibration (must turn off PLL). @@ -1292,10 +1318,10 @@ enum esp32s3_rtc_xtal_freq_e IRAM_ATTR esp32s3_rtc_clk_xtal_freq_get(void) } /**************************************************************************** - * Name: esp32s3_rtc_clk_bbpll_disable + * Name: esp32_rtc_bbpll_disable * * Description: - * Disable BBPLL. + * Power down BBPLL circuit. * * Input Parameters: * None @@ -1305,12 +1331,32 @@ enum esp32s3_rtc_xtal_freq_e IRAM_ATTR esp32s3_rtc_clk_xtal_freq_get(void) * ****************************************************************************/ -static void IRAM_ATTR esp32s3_rtc_clk_bbpll_disable(void) +static void IRAM_ATTR esp32s3_rtc_bbpll_disable(void) { modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, 0, RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); } +/**************************************************************************** + * Name: esp32s3_rtc_bbpll_enable + * + * Description: + * Power up BBPLL circuit. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_rtc_bbpll_enable(void) +{ + modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); +} + /**************************************************************************** * Name: esp32s3_rtc_bbpll_configure * @@ -1329,26 +1375,36 @@ static void IRAM_ATTR esp32s3_rtc_clk_bbpll_disable(void) static void IRAM_ATTR esp32s3_rtc_bbpll_configure( enum esp32s3_rtc_xtal_freq_e xtal_freq, int pll_freq) { - static uint8_t div_ref = 0; - static uint8_t div7_0 = 0; - static uint8_t dr1 = 0 ; - static uint8_t dr3 = 0 ; - static uint8_t dchgp = 0; - static uint8_t dcur = 0; - static uint8_t dbias = 0; - uint8_t i2c_bbpll_lref = 0; + uint8_t div_ref = 0; + uint8_t div7_0 = 0; + uint8_t dr1 = 0; + uint8_t dr3 = 0; + uint8_t dchgp = 0; + uint8_t dcur = 0; + uint8_t dbias = 3; + uint8_t i2c_bbpll_lref = 0; uint8_t i2c_bbpll_div_7_0 = 0; uint8_t i2c_bbpll_dcur = 0; + switch (pll_freq) + { + case RTC_PLL_FREQ_320M: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 0); + break; + + case RTC_PLL_FREQ_480M: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 1); + break; + + default: + DEBUGASSERT(0); + } + modifyreg32(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, 0); modifyreg32(I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW); if (pll_freq == RTC_PLL_FREQ_480M) { - /* Set this register to let the digital part know 480M PLL is used */ - - modifyreg32(SYSTEM_CPU_PER_CONF_REG, 0, SYSTEM_PLL_FREQ_SEL); - /* Configure 480M PLL */ switch (xtal_freq) @@ -1361,7 +1417,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; @@ -1373,7 +1428,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 1; dchgp = 4; dcur = 0; - dbias = 2; } break; @@ -1385,7 +1439,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; } @@ -1394,11 +1447,7 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( } else { - /* Clear this register to let the digital part know 320M PLL is used */ - - modifyreg32(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 0); - - /* Configure 480M PLL */ + /* Configure 320M PLL */ switch (xtal_freq) { @@ -1410,7 +1459,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; @@ -1422,7 +1470,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; @@ -1434,7 +1481,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; } @@ -1445,7 +1491,7 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref); i2c_bbpll_div_7_0 = div7_0; i2c_bbpll_dcur = (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | - (2 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; + (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); @@ -1530,6 +1576,18 @@ void IRAM_ATTR esp32s3_rtc_init(void) cfg.cali_ocode = 1; } + /* When run rtc_init, it maybe deep sleep reset. Since we power down modem + * in deep sleep, after wakeup from deep sleep, these fields are changed + * and not reset. We will access two BB regs(BBPD_CTRL and NRXPD_CTRL) in + * rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these + * two BB regs and finally triggle RTC WDT. So need to clear modem Force + * PD. No worry about the power consumption, Because modem Force PD will + * be set at the end of this function. + */ + + modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO, 0); + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD, 0); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); @@ -1941,9 +1999,8 @@ uint32_t esp32s3_rtc_clk_apb_freq_get(void) void IRAM_ATTR esp32s3_rtc_cpu_freq_set_xtal(void) { - int freq_mhz = (int) esp32s3_rtc_clk_xtal_freq_get(); + int freq_mhz = (int)esp32s3_rtc_clk_xtal_freq_get(); esp32s3_rtc_update_to_xtal(freq_mhz, 1); - esp32s3_rtc_wait_for_slow_cycle(); esp32s3_rtc_bbpll_disable(); } @@ -2383,15 +2440,16 @@ void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_set_config( esp32s3_rtc_update_to_xtal(config->freq_mhz, config->div); if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - esp32s3_rtc_clk_bbpll_disable(); + esp32s3_rtc_bbpll_disable(); } } else if (config->source == RTC_CPU_FREQ_SRC_PLL) { if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { + esp32s3_rtc_bbpll_enable(); modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); esp32s3_rtc_bbpll_configure(esp32s3_rtc_clk_xtal_freq_get(), config->source_freq_mhz); } @@ -2403,7 +2461,7 @@ void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_set_config( esp32s3_rtc_clk_cpu_freq_to_8m(); if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - esp32s3_rtc_clk_bbpll_disable(); + esp32s3_rtc_bbpll_disable(); } } } @@ -2535,46 +2593,6 @@ uint64_t esp32s3_rtc_get_time_us(void) return delta_time_us; } -/**************************************************************************** - * Name: esp32s3_rtc_bbpll_enable - * - * Description: - * Power up BBPLL circuit. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void IRAM_ATTR esp32s3_rtc_bbpll_enable(void) -{ - modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); -} - -/**************************************************************************** - * Name: esp32_rtc_bbpll_disable - * - * Description: - * Power down BBPLL circuit. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void IRAM_ATTR esp32s3_rtc_bbpll_disable(void) -{ - modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, 0, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); -} - /**************************************************************************** * Name: esp32c3_rtc_sleep_low_init * @@ -2661,13 +2679,27 @@ uint64_t IRAM_ATTR esp32s3_rtc_get_boot_time(void) #ifdef CONFIG_ESP32S3_SYSTEM_BBPLL_RECALIB void IRAM_ATTR esp32s3_rtc_recalib_bbpll(void) { - struct esp32s3_cpu_freq_config_s freq_config; + struct esp32s3_cpu_freq_config_s freq_config = + { + 0 + }; + esp32s3_rtc_clk_cpu_freq_get_config(&freq_config); - esp32s3_rtc_cpu_freq_set_xtal(); - esp32s3_rtc_bbpll_disable(); - esp32s3_rtc_bbpll_enable(); - esp32s3_rtc_bbpll_configure(esp32s3_rtc_clk_xtal_freq_get(), 480); - esp32s3_rtc_clk_cpu_freq_set_config(&freq_config); + + /* There are two paths we arrive here: 1.CPU reset. 2.Other reset reasons. + * - For other reasons, the bootloader will set CPU source to BBPLL and + * enable it. But there are calibration issues. Turn off the BBPLL and + * do calibration again to fix the issue. + * - For CPU reset, the CPU source will be set to XTAL, while the BBPLL + * is kept to meet USB Serial JTAG's requirements. In this case, we + * don't touch BBPLL to avoid USJ disconnection. + */ + + if (freq_config.source == RTC_CPU_FREQ_SRC_PLL) + { + esp32s3_rtc_cpu_freq_set_xtal(); + esp32s3_rtc_clk_cpu_freq_set_config(&freq_config); + } } #endif diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.h b/arch/xtensa/src/esp32s3/esp32s3_rtc.h index 7ad11eec4dc90..9b4f4464daecd 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.h +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.h @@ -301,22 +301,6 @@ enum esp32s3_rtc_xtal_freq_e esp32s3_rtc_clk_xtal_freq_get(void); void esp32s3_rtc_update_to_xtal(int freq, int div); -/**************************************************************************** - * Name: esp32s3_rtc_bbpll_enable - * - * Description: - * Reset BBPLL configuration. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void esp32s3_rtc_bbpll_enable(void); - /**************************************************************************** * Name: esp32s3_rtc_clk_set * @@ -434,22 +418,6 @@ uint64_t esp32s3_rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t esp32s3_clk_slowclk_cal_get(void); -/**************************************************************************** - * Name: esp32s3_rtc_bbpll_disable - * - * Description: - * disable BBPLL. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void esp32s3_rtc_bbpll_disable(void); - /**************************************************************************** * Name: esp32s3_rtc_sleep_set_wakeup_time * diff --git a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h index 3a8ab206f0c1a..8b26a01a815a5 100644 --- a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h +++ b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h @@ -5843,6 +5843,13 @@ #define RTC_CNTL_DATE_V 0x0fffffff #define RTC_CNTL_DATE_S 0 +/* LDO SLAVE : R/W ;bitpos:[18:13] ; default: 6'd0 ; */ + +#define RTC_CNTL_SLAVE_PD 0x0000003F +#define RTC_CNTL_SLAVE_PD_M ((RTC_CNTL_SLAVE_PD_V)<<(RTC_CNTL_SLAVE_PD_S)) +#define RTC_CNTL_SLAVE_PD_V 0x3f +#define RTC_CNTL_SLAVE_PD_S 13 + /* Deep sleep (power down digital domain) */ #define RTC_SLEEP_PD_DIG BIT(0) diff --git a/arch/z16/include/types.h b/arch/z16/include/types.h index 1b9a51c306df5..e2719f5705701 100644 --- a/arch/z16/include/types.h +++ b/arch/z16/include/types.h @@ -66,6 +66,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z80/include/ez80/types.h b/arch/z80/include/ez80/types.h index 734e35351f335..d852729de3c0e 100644 --- a/arch/z80/include/ez80/types.h +++ b/arch/z80/include/ez80/types.h @@ -90,6 +90,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A pointer is 2 or 3 bytes, depending upon if the ez80 is in z80 * compatibility mode or not * diff --git a/arch/z80/include/z180/types.h b/arch/z80/include/z180/types.h index 9f58ba29d03d2..438c82e414d1f 100644 --- a/arch/z80/include/z180/types.h +++ b/arch/z80/include/z180/types.h @@ -78,6 +78,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z80/include/z8/types.h b/arch/z80/include/z8/types.h index 72e3b7164d72c..8baf908c97dfc 100644 --- a/arch/z80/include/z8/types.h +++ b/arch/z80/include/z8/types.h @@ -82,6 +82,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z80/include/z80/types.h b/arch/z80/include/z80/types.h index f8efd7ae88334..bd64f657c0954 100644 --- a/arch/z80/include/z80/types.h +++ b/arch/z80/include/z80/types.h @@ -78,6 +78,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/binfmt/libelf/libelf_coredump.c b/binfmt/libelf/libelf_coredump.c index 725992a9ae15a..f5f5ccd2c452e 100644 --- a/binfmt/libelf/libelf_coredump.c +++ b/binfmt/libelf/libelf_coredump.c @@ -423,9 +423,34 @@ static void elf_emit_memory(FAR struct elf_dumpinfo_s *cinfo, int memsegs) for (i = 0; i < memsegs; i++) { - elf_emit(cinfo, (FAR void *)cinfo->regions[i].start, - cinfo->regions[i].end - - cinfo->regions[i].start); + if (cinfo->regions[i].flags & PF_REGISTER) + { + FAR uintptr_t *start = (FAR uintptr_t *)cinfo->regions[i].start; + FAR uintptr_t *end = (FAR uintptr_t *)cinfo->regions[i].end; + uintptr_t buf[64]; + size_t offset = 0; + + while (start < end) + { + buf[offset++] = *start++; + + if (offset % (sizeof(buf) / sizeof(uintptr_t)) == 0) + { + elf_emit(cinfo, buf, sizeof(buf)); + offset = 0; + } + } + + if (offset != 0) + { + elf_emit(cinfo, buf, offset * sizeof(uintptr_t)); + } + } + else + { + elf_emit(cinfo, (FAR void *)cinfo->regions[i].start, + cinfo->regions[i].end - cinfo->regions[i].start); + } /* Align to page */ diff --git a/boards/arm/mps/mps3-an547/configs/nsh/defconfig b/boards/arm/mps/mps3-an547/configs/nsh/defconfig index 63f915480bdad..a98c6e92a2772 100644 --- a/boards/arm/mps/mps3-an547/configs/nsh/defconfig +++ b/boards/arm/mps/mps3-an547/configs/nsh/defconfig @@ -5,6 +5,7 @@ # You can then do "make savedefconfig" to generate a new defconfig file that includes your # modifications. # +# CONFIG_DEBUG_WARN is not set CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="mps3-an547" CONFIG_ARCH_BOARD_MPS3_AN547=y @@ -12,6 +13,7 @@ CONFIG_ARCH_CHIP="mps" CONFIG_ARCH_CHIP_MPS3_AN547=y CONFIG_ARCH_CHIP_MPS=y CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y CONFIG_ARMV8M_SYSTICK=y CONFIG_BUILTIN=y CONFIG_CMSDK_UART0=y @@ -26,8 +28,6 @@ CONFIG_DEBUG_ASSERTIONS=y CONFIG_DEBUG_FEATURES=y CONFIG_DEBUG_SCHED=y CONFIG_DEBUG_SCHED_ERROR=y -CONFIG_DEBUG_SCHED_INFO=y -CONFIG_DEBUG_SCHED_WARN=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DEFAULT_TASK_STACKSIZE=4096 CONFIG_DEV_ZERO=y diff --git a/boards/arm/mps/mps3-an547/src/Makefile b/boards/arm/mps/mps3-an547/src/Makefile index 59ae8876b5dfb..c137aed2dda5b 100644 --- a/boards/arm/mps/mps3-an547/src/Makefile +++ b/boards/arm/mps/mps3-an547/src/Makefile @@ -20,6 +20,6 @@ include $(TOPDIR)/Make.defs -CSRCS = mps3_bringup.c +CSRCS = mps3_bringup.c mps3_reset.c include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/mps/mps3-an547/src/mps3_reset.c b/boards/arm/mps/mps3-an547/src/mps3_reset.c new file mode 100644 index 0000000000000..5b6bb37118d95 --- /dev/null +++ b/boards/arm/mps/mps3-an547/src/mps3_reset.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * boards/arm/mps/mps3-an547/src/mps3_reset.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + up_systemreset(); + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */ diff --git a/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c b/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c index c870a77e243df..0d48fb45a0ebd 100644 --- a/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c +++ b/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c @@ -384,10 +384,12 @@ static ssize_t smbus_sbd_write(struct file *filep, const char *buffer, * ****************************************************************************/ -static int smbus_sbd_callback(void *arg, size_t rx_len) +static int smbus_sbd_callback(void *arg, i2c_slave_complete_t state, + size_t rx_len) { struct smbus_sbd_dev_s *dev; int buffer_length; + int ret = OK; int i; /* Retrieve the pointer to the SMBus SBD slave device struct */ @@ -726,8 +728,15 @@ static int smbus_sbd_callback(void *arg, size_t rx_len) * request has been received. */ - return I2CS_WRITE(dev->i2c_slave_dev, (const uint8_t *)dev->write_buffer, - buffer_length); + ret = I2CS_WRITE(dev->i2c_slave_dev, (const uint8_t *)dev->write_buffer, + buffer_length); + if (ret >= 0) + { + dev->i2c_slave_dev->callback(dev->i2c_slave_dev->callback_arg, + I2CS_TX_COMPLETE, buffer_length); + } + + return ret; } /**************************************************************************** diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c b/boards/arm/stm32/common/include/stm32_bmp280.h similarity index 57% rename from boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c rename to boards/arm/stm32/common/include/stm32_bmp280.h index cb20cf6155a79..9c15ff6f610d1 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c +++ b/boards/arm/stm32/common/include/stm32_bmp280.h @@ -1,5 +1,5 @@ /**************************************************************************** - * boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c + * boards/arm/stm32/common/include/stm32_bmp280.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,69 +18,67 @@ * ****************************************************************************/ +#ifndef __BOARDS_ARM_STM32_COMMON_INCLUDE_STM32_BMP280_H +#define __BOARDS_ARM_STM32_COMMON_INCLUDE_STM32_BMP280_H + /**************************************************************************** * Included Files ****************************************************************************/ #include -#include -#include - -#include -#include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#include "stm32.h" -#include "stm32_spi.h" -#include "stm32f103_minimum.h" +/**************************************************************************** + * Type Definitions + ****************************************************************************/ -#if defined(CONFIG_SPI) && defined(CONFIG_STM32_SPI1) && defined(CONFIG_CL_MFRC522) +/**************************************************************************** + * Public Types + ****************************************************************************/ /**************************************************************************** - * Pre-processor Definitions + * Public Data ****************************************************************************/ -#define MFRC522_SPI_PORTNO 1 /* On SPI1 */ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif /**************************************************************************** - * Public Functions + * Inline Functions ****************************************************************************/ /**************************************************************************** - * Name: stm32_mfrc522initialize + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_bmp280_initialize * * Description: - * Initialize and register the MFRC522 RFID driver. + * Initialize and register the BMP280 Pressure Sensor driver. * * Input Parameters: - * devpath - The full path to the driver to register. E.g., "/dev/rfid0" + * devno - The device number, used to build the device path as /dev/pressN + * busno - The I2C bus number * * Returned Value: * Zero (OK) on success; a negated errno value on failure. * ****************************************************************************/ -int stm32_mfrc522initialize(const char *devpath) -{ - struct spi_dev_s *spi; - int ret; - - spi = stm32_spibus_initialize(MFRC522_SPI_PORTNO); - - if (!spi) - { - return -ENODEV; - } - - /* Then register the MFRC522 */ - - ret = mfrc522_register(devpath, spi); - if (ret < 0) - { - snerr("ERROR: Error registering MFRC522\n"); - } +int board_bmp280_initialize(int devno, int busno); - return ret; +#undef EXTERN +#ifdef __cplusplus } +#endif -#endif /* CONFIG_SPI && CONFIG_MFRC522 */ +#endif /* __BOARDS_ARM_STM32_COMMON_INCLUDE_STM32_BMP280_H */ diff --git a/boards/arm/stm32/common/src/CMakeLists.txt b/boards/arm/stm32/common/src/CMakeLists.txt index 4c6c4df796d34..668cb257f669d 100644 --- a/boards/arm/stm32/common/src/CMakeLists.txt +++ b/boards/arm/stm32/common/src/CMakeLists.txt @@ -24,6 +24,10 @@ if(CONFIG_SENSORS_BMP180) list(APPEND SRCS stm32_bmp180.c) endif() +if(CONFIG_SENSORS_BMP280) + list(APPEND SRCS stm32_bmp280.c) +endif() + if(CONFIG_LEDS_APA102) list(APPEND SRCS stm32_apa102.c) endif() diff --git a/boards/arm/stm32/common/src/Make.defs b/boards/arm/stm32/common/src/Make.defs index ddb698c13b3f6..fc75a96098b97 100644 --- a/boards/arm/stm32/common/src/Make.defs +++ b/boards/arm/stm32/common/src/Make.defs @@ -24,6 +24,10 @@ ifeq ($(CONFIG_SENSORS_BMP180),y) CSRCS += stm32_bmp180.c endif +ifeq ($(CONFIG_SENSORS_BMP280),y) + CSRCS += stm32_bmp280.c +endif + ifeq ($(CONFIG_SENSORS_MS56XX),y) CSRCS += stm32_ms5611.c endif diff --git a/boards/arm/stm32/common/src/stm32_bmp280.c b/boards/arm/stm32/common/src/stm32_bmp280.c new file mode 100644 index 0000000000000..b8b0f70ebfa91 --- /dev/null +++ b/boards/arm/stm32/common/src/stm32_bmp280.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * boards/arm/stm32/common/src/stm32_bmp280.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "stm32_i2c.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_bmp280_initialize + * + * Description: + * Initialize and register the BMP280 Pressure Sensor driver. + * + * Input Parameters: + * devno - The device number, used to build the device path as /dev/pressN + * busno - The I2C bus number + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_bmp280_initialize(int devno, int busno) +{ + struct i2c_master_s *i2c; + int ret; + + sninfo("Initializing BMP280!\n"); + + /* Initialize BMP280 */ + + i2c = stm32_i2cbus_initialize(busno); + if (i2c) + { + /* Then try to register the barometer sensor in I2C0 */ + + ret = bmp280_register(devno, i2c); + if (ret < 0) + { + snerr("ERROR: Error registering BMP280 in I2C%d\n", busno); + } + } + else + { + ret = -ENODEV; + } + + return ret; +} + diff --git a/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig b/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig index 5bb78a6b9431f..e36cee0693e38 100644 --- a/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig +++ b/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig @@ -19,6 +19,7 @@ # CONFIG_NSH_DISABLE_XD is not set CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="stm32f103-minimum" +CONFIG_ARCH_BOARD_COMMON=y CONFIG_ARCH_BOARD_STM32F103_MINIMUM=y CONFIG_ARCH_CHIP="stm32" CONFIG_ARCH_CHIP_STM32=y diff --git a/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt b/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt index fa92900f2d3f2..0fc22fd9dc5d8 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt +++ b/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt @@ -79,10 +79,6 @@ if(CONFIG_CAN_MCP2515) list(APPEND SRCS stm32_mcp2515.c) endif() -if(CONFIG_CL_MFRC522) - list(APPEND SRCS stm32_mfrc522.c) -endif() - if(CONFIG_LCD_MAX7219) list(APPEND SRCS stm32_max7219.c) endif() diff --git a/boards/arm/stm32/stm32f103-minimum/src/Make.defs b/boards/arm/stm32/stm32f103-minimum/src/Make.defs index 651c06d46b134..10c18a339cbb9 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/Make.defs +++ b/boards/arm/stm32/stm32f103-minimum/src/Make.defs @@ -81,10 +81,6 @@ ifeq ($(CONFIG_CAN_MCP2515),y) CSRCS += stm32_mcp2515.c endif -ifeq ($(CONFIG_CL_MFRC522),y) - CSRCS += stm32_mfrc522.c -endif - ifeq ($(CONFIG_LCD_MAX7219),y) CSRCS += stm32_max7219.c endif diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c b/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c index d228b1bc9c61e..16d4a8c9fc610 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c +++ b/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c @@ -56,6 +56,10 @@ # include #endif +#ifdef CONFIG_CL_MFRC522 +#include "stm32_mfrc522.h" +#endif + #include "stm32f103_minimum.h" /* Conditional logic in stm32f103_minimum.h will determine if certain diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h b/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h index 44929f9453b4a..fbdcf126516d0 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h +++ b/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h @@ -372,17 +372,5 @@ int stm32_hyt271initialize(int devno); int stm32_ds18b20initialize(int devno); #endif -/**************************************************************************** - * Name: stm32_mfrc522initialize - * - * Description: - * Function used to initialize the MFRC522 RFID Transceiver - * - ****************************************************************************/ - -#ifdef CONFIG_CL_MFRC522 -int stm32_mfrc522initialize(const char *devpath); -#endif - #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_STM32_STM32F103_MINIMUM_SRC_STM32F103_MINIMUM_H */ diff --git a/boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig b/boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig new file mode 100644 index 0000000000000..20d75c29f72dc --- /dev/null +++ b/boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig @@ -0,0 +1,69 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32f401rc-rs485" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_STM32F401RC_RS485=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="stm32" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F401RC=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BMP280_I2C_ADDR_77=y +CONFIG_BOARDCTL_USBDEVCTRL=y +CONFIG_BOARD_LOOPSPERMSEC=8499 +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_CONSOLE=y +CONFIG_EXAMPLES_BMP280=y +CONFIG_EXAMPLES_BUTTONS=y +CONFIG_EXAMPLES_BUTTONS_NAME0="SW3" +CONFIG_EXAMPLES_BUTTONS_NAME1="SW4" +CONFIG_EXAMPLES_BUTTONS_NAME2="SW5" +CONFIG_EXAMPLES_BUTTONS_NAMES=y +CONFIG_EXAMPLES_BUTTONS_QTD=3 +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_BUTTONS=y +CONFIG_INPUT_BUTTONS_LOWER=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=98304 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SENSORS=y +CONFIG_SENSORS_BMP280=y +CONFIG_SPI=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=5 +CONFIG_START_YEAR=2014 +CONFIG_STM32_I2C1=y +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_OTGFS=y +CONFIG_STM32_PWR=y +CONFIG_STM32_USART6=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USBDEV=y diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c index cd8f236be0426..b513580b4f739 100644 --- a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c +++ b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c @@ -75,6 +75,10 @@ #include "stm32_drv8266.h" #endif +#ifdef CONFIG_SENSORS_BMP280 +#include "stm32_bmp280.h" +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -298,5 +302,16 @@ int stm32_bringup(void) } #endif +#ifdef CONFIG_SENSORS_BMP280 + /* Initialize the BMP280 pressure sensor. */ + + ret = board_bmp280_initialize(0, 1); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize BMP280, error %d\n", ret); + return ret; + } +#endif + return ret; } diff --git a/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig new file mode 100644 index 0000000000000..7b1048fb5fec5 --- /dev/null +++ b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig @@ -0,0 +1,47 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32h745i-disco" +CONFIG_ARCH_BOARD_STM32H745I_DISCO=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H745XI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM4=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_PROMPT_STRING="nsh-cm4> " +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x10000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_FMC=y +CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY=y +CONFIG_STM32H7_UART7=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_UART7_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig new file mode 100644 index 0000000000000..bcc2fad0802c3 --- /dev/null +++ b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig @@ -0,0 +1,51 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_STANDARD_SERIAL is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32h745i-disco" +CONFIG_ARCH_BOARD_STM32H745I_DISCO=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H745XI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=4 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_PROMPT_STRING="nsh-cm7> " +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_FMC=y +CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY=y +CONFIG_STM32H7_USART3=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART3_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h7/stm32h745i-disco/include/board.h b/boards/arm/stm32h7/stm32h745i-disco/include/board.h index 461d5268f6a65..cb8a113598125 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/include/board.h +++ b/boards/arm/stm32h7/stm32h745i-disco/include/board.h @@ -502,6 +502,11 @@ #define GPIO_USART3_RX (GPIO_USART3_RX_1 | GPIO_SPEED_100MHz) /* PB11 */ #define GPIO_USART3_TX (GPIO_USART3_TX_1 | GPIO_SPEED_100MHz) /* PB10 */ +/* UART7 (Discovery Virtual Console) */ + +#define GPIO_UART7_RX (GPIO_UART7_RX_1 | GPIO_SPEED_100MHz) /* PA8 */ +#define GPIO_UART7_TX (GPIO_UART7_TX_2 | GPIO_SPEED_100MHz) /* PB4 */ + /* I2C4 - Used by Touchscreen and Audio Codec */ #define GPIO_I2C4_SCL (GPIO_I2C4_SCL_1 | GPIO_SPEED_50MHz) /* PD12 */ diff --git a/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs b/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs index 53f84d9234439..fb95f1de7a191 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs +++ b/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs @@ -22,7 +22,11 @@ include $(TOPDIR)/.config include $(TOPDIR)/tools/Config.mk include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs -LDSCRIPT = flash.ld +ifeq ($(CONFIG_ARCH_CHIP_STM32H7_CORTEXM7),y) + LDSCRIPT = flash.ld +else + LDSCRIPT = flash_m4.ld +endif ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) diff --git a/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld index 958e111c19aed..1257c37ee9495 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld +++ b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld @@ -93,6 +93,9 @@ * the 0x0800:0000 address range. */ +#include + +#ifndef CONFIG_STM32H7_CORTEXM4_ENABLED MEMORY { itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K @@ -106,6 +109,22 @@ MEMORY sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K } +#else +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + flash (rx) : ORIGIN = 0x08000000, LENGTH = CONFIG_STM32H7_CORTEXM7_FLASH_SIZE + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + + /* shared memory on SRAM3 */ + + shmem (rwx) : ORIGIN = 0x30040000, LENGTH = 32K + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} +#endif OUTPUT_ARCH(arm) EXTERN(_vectors) @@ -170,6 +189,13 @@ SECTIONS _ebss = ABSOLUTE(.); } > sram + .shmem : + { + . = ALIGN(4); + *(.shmem); + KEEP(*(.shmem)) + } > shmem + /* Emit the the D3 power domain section for locating BDMA data * * Static data with locate_data(".sram4") will be located diff --git a/boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld new file mode 100644 index 0000000000000..c453148555f11 --- /dev/null +++ b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld @@ -0,0 +1,123 @@ +/**************************************************************************** + * boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (theflash.ld + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#include + +#define STM32M4_FLASH_START (0x08000000 + CONFIG_STM32H7_CORTEXM7_FLASH_SIZE) + +#if CONFIG_STM32H7_CORTEXM7_FLASH_SIZE != 1048576 +# error TODO: not supported yet - BCM4_ADD0 must be configured +#endif + +/* Use 0x1xxxxxxx SRAM1-3 mapping for Cortex-M4 */ + +MEMORY +{ + flash (rx) : + ORIGIN = STM32M4_FLASH_START, + LENGTH = (2048K - CONFIG_STM32H7_CORTEXM7_FLASH_SIZE) + + /* SRAM1 and SRAM2 */ + + sram (rwx) : ORIGIN = 0x10000000, LENGTH = 128K + 128K + + /* shared memory on SRAM3 */ + + shmem (rwx) : ORIGIN = 0x10040000, LENGTH = 32K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt b/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt index 985622e7f71ab..caab40630ab0f 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt +++ b/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt @@ -52,4 +52,9 @@ endif() target_sources(board PRIVATE ${SRCS}) -set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") +if(CONFIG_ARCH_CHIP_STM32H7_CORTEXM7) + set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") +else() + set_property(GLOBAL PROPERTY LD_SCRIPT + "${NUTTX_BOARD_DIR}/scripts/flash_m4.ld") +endif() diff --git a/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c b/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c index 9f15fd0eb52e8..0e8056aa764a8 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c +++ b/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c @@ -53,7 +53,7 @@ static const uint32_t g_ledcfg[BOARD_NLEDS] = { GPIO_LED_GREEN, - GPIO_LED_BLUE, + GPIO_LED_ORANGE, GPIO_LED_RED, }; diff --git a/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig b/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig index ba029f9a37bea..3b157590f2770 100644 --- a/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig +++ b/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig @@ -91,7 +91,6 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_SYSTEM_DHCPC_RENEW=y CONFIG_SYSTEM_NETDB=y CONFIG_SYSTEM_NSH=y -CONFIG_SYSTEM_NTPC=y CONFIG_SYSTEM_PING=y CONFIG_TASK_NAME_SIZE=24 CONFIG_TESTING_OSTEST=y diff --git a/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt index 6f5e40d723db9..a7c54dabdbbfd 100644 --- a/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt @@ -19,3 +19,10 @@ # ############################################################################## add_subdirectory(src) + +if(CONFIG_BUILD_PROTECTED) + add_subdirectory(kernel) + set_property( + GLOBAL PROPERTY LD_SCRIPT_USER + ${CMAKE_CURRENT_LIST_DIR}/scripts/ld-userland.script) +endif() diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh32/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/knsh32/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/knsh/defconfig diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh32_paging/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/knsh32_paging/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh32_romfs/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh_romfs/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/knsh32_romfs/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/knsh_romfs/defconfig diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig new file mode 100644 index 0000000000000..696083e9846ed --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig @@ -0,0 +1,76 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +CONFIG_16550_ADDRWIDTH=0 +CONFIG_16550_UART0=y +CONFIG_16550_UART0_BASE=0x10000000 +CONFIG_16550_UART0_CLOCK=3686400 +CONFIG_16550_UART0_IRQ=37 +CONFIG_16550_UART0_SERIAL_CONSOLE=y +CONFIG_16550_UART=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="rv-virt" +CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y +CONFIG_ARCH_CHIP="qemu-rv" +CONFIG_ARCH_CHIP_QEMU_RV64=y +CONFIG_ARCH_CHIP_QEMU_RV=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_M=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BCH=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=6366 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEVICE_TREE=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_LEDS=y +CONFIG_EXAMPLES_LEDS_RUST=y +CONFIG_FS_HOSTFS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIBM=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/system/bin" +CONFIG_RAM_SIZE=33554432 +CONFIG_RAM_START=0x80000000 +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RISCV_SEMIHOSTING_HOSTFS=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_UART_ARCH_MMIO=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2021 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=3072 +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/libcxx32/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/libcxx/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/libcxx32/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/libcxx/defconfig diff --git a/arch/risc-v/src/common/supervisor/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt similarity index 81% rename from arch/risc-v/src/common/supervisor/CMakeLists.txt rename to boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt index 376ded80b308c..82638d9cc026f 100644 --- a/arch/risc-v/src/common/supervisor/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt @@ -1,5 +1,5 @@ # ############################################################################## -# arch/risc-v/src/common/supervisor/CMakeLists.txt +# boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt # # Licensed to the Apache Software Foundation (ASF) under one or more contributor # license agreements. See the NOTICE file distributed with this work for @@ -18,11 +18,4 @@ # # ############################################################################## -if(CONFIG_ARCH_USE_S_MODE) - set(SRCS) - - list(APPEND SRCS riscv_syscall.S riscv_perform_syscall.c riscv_sbi.c) - - target_sources(arch PRIVATE ${SRCS}) - -endif() +target_sources(nuttx_user PRIVATE rv_virt_userspace.c) diff --git a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt index e5f78691fd703..46e760f6ccefd 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt @@ -31,9 +31,12 @@ endif() target_sources(board PRIVATE ${SRCS}) if(CONFIG_ARCH_CHIP_QEMU_RV) - - if(CONFIG_BUILD_KERNEL) + if(CONFIG_NUTTSBI) + set(LDFILE ld-nuttsbi.script) + elseif(CONFIG_BUILD_KERNEL) set(LDFILE ld-kernel.script) + elseif(CONFIG_BUILD_PROTECTED) + set(LDFILE ld-protected.script) else() set(LDFILE ld.script) endif() diff --git a/boards/sim/sim/sim/configs/login/defconfig b/boards/sim/sim/sim/configs/login/defconfig new file mode 100644 index 0000000000000..fbb4f2874e791 --- /dev/null +++ b/boards/sim/sim/sim/configs/login/defconfig @@ -0,0 +1,67 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="sim" +CONFIG_ARCH_BOARD="sim" +CONFIG_ARCH_BOARD_SIM=y +CONFIG_ARCH_CHIP="sim" +CONFIG_ARCH_SIM=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LOOPSPERMSEC=0 +CONFIG_BOOT_RUNFROMEXTSRAM=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_GPIO=y +CONFIG_DEV_LOOP=y +CONFIG_DEV_ZERO=y +CONFIG_ETC_FATDEVNO=2 +CONFIG_ETC_ROMFS=y +CONFIG_ETC_ROMFSDEVNO=1 +CONFIG_EXAMPLES_GPIO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FSUTILS_PASSWD=y +CONFIG_FSUTILS_PASSWD_READONLY=y +CONFIG_FS_BINFS=y +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_FS_RAMMAP=y +CONFIG_FS_ROMFS=y +CONFIG_GPIO_LOWER_HALF=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_IOEXPANDER=y +CONFIG_IOEXPANDER_DUMMY=y +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_LOCALE=y +CONFIG_LIBC_LOCALE_CATALOG=y +CONFIG_LIBC_LOCALE_GETTEXT=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_LIBC_NUMBERED_ARGS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CONSOLE_LOGIN=y +CONFIG_NSH_FILE_APPS=y +CONFIG_NSH_MOTD=y +CONFIG_NSH_MOTD_STRING="MOTD: username=admin password=Administrator" +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/bin" +CONFIG_PSEUDOFS_ATTRIBUTES=y +CONFIG_PSEUDOFS_SOFTLINKS=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIM_WALLTIME_SIGNAL=y +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2008 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y diff --git a/boards/sim/sim/sim/configs/lvgl_fb/defconfig b/boards/sim/sim/sim/configs/lvgl_fb/defconfig index 89c589c3c98ad..7b5c75721149e 100644 --- a/boards/sim/sim/sim/configs/lvgl_fb/defconfig +++ b/boards/sim/sim/sim/configs/lvgl_fb/defconfig @@ -46,7 +46,6 @@ CONFIG_NXFONTS_DISABLE_2BPP=y CONFIG_NXFONTS_DISABLE_32BPP=y CONFIG_NXFONTS_DISABLE_4BPP=y CONFIG_NXFONTS_DISABLE_8BPP=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=480 CONFIG_SIM_FBWIDTH=640 CONFIG_SIM_TOUCHSCREEN=y diff --git a/boards/sim/sim/sim/configs/lvgl_lcd/defconfig b/boards/sim/sim/sim/configs/lvgl_lcd/defconfig index f4473002c5540..db78a72ec12b1 100644 --- a/boards/sim/sim/sim/configs/lvgl_lcd/defconfig +++ b/boards/sim/sim/sim/configs/lvgl_lcd/defconfig @@ -49,7 +49,6 @@ CONFIG_NXFONTS_DISABLE_2BPP=y CONFIG_NXFONTS_DISABLE_32BPP=y CONFIG_NXFONTS_DISABLE_4BPP=y CONFIG_NXFONTS_DISABLE_8BPP=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=480 CONFIG_SIM_FBWIDTH=640 CONFIG_SIM_TOUCHSCREEN=y diff --git a/boards/sim/sim/sim/configs/nsh/defconfig b/boards/sim/sim/sim/configs/nsh/defconfig index fbb4f2874e791..094b594c88194 100644 --- a/boards/sim/sim/sim/configs/nsh/defconfig +++ b/boards/sim/sim/sim/configs/nsh/defconfig @@ -27,8 +27,6 @@ CONFIG_EXAMPLES_GPIO=y CONFIG_EXAMPLES_HELLO=y CONFIG_FAT_LCNAMES=y CONFIG_FAT_LFN=y -CONFIG_FSUTILS_PASSWD=y -CONFIG_FSUTILS_PASSWD_READONLY=y CONFIG_FS_BINFS=y CONFIG_FS_FAT=y CONFIG_FS_PROCFS=y @@ -48,10 +46,7 @@ CONFIG_LIBC_MAX_EXITFUNS=1 CONFIG_LIBC_NUMBERED_ARGS=y CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y -CONFIG_NSH_CONSOLE_LOGIN=y CONFIG_NSH_FILE_APPS=y -CONFIG_NSH_MOTD=y -CONFIG_NSH_MOTD_STRING="MOTD: username=admin password=Administrator" CONFIG_NSH_READLINE=y CONFIG_PATH_INITIAL="/bin" CONFIG_PSEUDOFS_ATTRIBUTES=y diff --git a/boards/sim/sim/sim/configs/nsh2/defconfig b/boards/sim/sim/sim/configs/nsh2/defconfig index e4bfdc0b851a2..8f6eff808585c 100644 --- a/boards/sim/sim/sim/configs/nsh2/defconfig +++ b/boards/sim/sim/sim/configs/nsh2/defconfig @@ -47,7 +47,6 @@ CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y CONFIG_SCHED_WAITPID=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_TOUCHSCREEN=y CONFIG_SIM_X11FB=y CONFIG_START_DAY=6 diff --git a/boards/sim/sim/sim/configs/nx11/defconfig b/boards/sim/sim/sim/configs/nx11/defconfig index 79ff26cb8eaa7..5f196b9d12b31 100644 --- a/boards/sim/sim/sim/configs/nx11/defconfig +++ b/boards/sim/sim/sim/configs/nx11/defconfig @@ -25,7 +25,6 @@ CONFIG_NXFONT_SANS23X27=y CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_X11FB=y CONFIG_START_DAY=28 CONFIG_START_MONTH=11 diff --git a/boards/sim/sim/sim/configs/nxcamera/defconfig b/boards/sim/sim/sim/configs/nxcamera/defconfig index faa3692029d8c..1b27f6e808fc1 100644 --- a/boards/sim/sim/sim/configs/nxcamera/defconfig +++ b/boards/sim/sim/sim/configs/nxcamera/defconfig @@ -57,7 +57,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y CONFIG_READLINE_TABCOMPLETION=y CONFIG_SCHED_BACKTRACE=y CONFIG_SCHED_HAVE_PARENT=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=480 CONFIG_SIM_FBWIDTH=640 CONFIG_SIM_X11FB=y diff --git a/boards/sim/sim/sim/configs/nxlines/defconfig b/boards/sim/sim/sim/configs/nxlines/defconfig index 234735d942078..f614d4acadf06 100644 --- a/boards/sim/sim/sim/configs/nxlines/defconfig +++ b/boards/sim/sim/sim/configs/nxlines/defconfig @@ -50,7 +50,6 @@ CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y CONFIG_SCHED_WAITPID=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_X11FB=y CONFIG_START_MONTH=5 CONFIG_START_YEAR=2012 diff --git a/boards/sim/sim/sim/configs/nxwm/defconfig b/boards/sim/sim/sim/configs/nxwm/defconfig index 6dd1c95594edc..af3c3f8fa38a6 100644 --- a/boards/sim/sim/sim/configs/nxwm/defconfig +++ b/boards/sim/sim/sim/configs/nxwm/defconfig @@ -46,7 +46,6 @@ CONFIG_NXWM_TASKBAR_LEFT=y CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_SCHED_WAITPID=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_X11FB=y CONFIG_START_MONTH=5 CONFIG_START_YEAR=2012 diff --git a/boards/sim/sim/sim/configs/touchscreen/defconfig b/boards/sim/sim/sim/configs/touchscreen/defconfig index 6a630a23391f2..170064350a592 100644 --- a/boards/sim/sim/sim/configs/touchscreen/defconfig +++ b/boards/sim/sim/sim/configs/touchscreen/defconfig @@ -29,7 +29,6 @@ CONFIG_NXFONT_SANS23X27=y CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=320 CONFIG_SIM_FBWIDTH=240 CONFIG_SIM_TOUCHSCREEN=y diff --git a/boards/sim/sim/sim/configs/windows/defconfig b/boards/sim/sim/sim/configs/windows/defconfig index be8e8b4a0dd00..dccfaa4d5103a 100644 --- a/boards/sim/sim/sim/configs/windows/defconfig +++ b/boards/sim/sim/sim/configs/windows/defconfig @@ -66,4 +66,5 @@ CONFIG_SIM_HOSTFS=y CONFIG_SIM_STACKSIZE_ADJUSTMENT=10240 CONFIG_SYSTEM_NSH=y CONFIG_SYSTEM_PING=y +CONFIG_SYSTEM_TIME64=y CONFIG_TESTING_OSTEST=y diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig b/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig index 0e08f0d287628..6b0aea34dc1bf 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig +++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig @@ -28,6 +28,7 @@ CONFIG_ESP32S3_RT_TIMER_TASK_STACK_SIZE=4096 CONFIG_ESP32S3_SPIFLASH=y CONFIG_ESP32S3_SPIRAM=y CONFIG_ESP32S3_SPIRAM_MODE_OCT=y +CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK=y CONFIG_ESP32S3_STORAGE_MTD_SIZE=0x1e80000 CONFIG_ESP32S3_UART0=y CONFIG_ESP32S3_WIFI=y @@ -71,7 +72,6 @@ CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAM_SIZE=114688 CONFIG_RAM_START=0x20000000 CONFIG_RR_INTERVAL=200 -CONFIG_SCHED_LPWORK=y CONFIG_SCHED_WAITPID=y CONFIG_SIG_DEFAULT=y CONFIG_SMP=y diff --git a/cmake/menuconfig.cmake b/cmake/menuconfig.cmake index 66d45bad95919..97e130712b4ba 100644 --- a/cmake/menuconfig.cmake +++ b/cmake/menuconfig.cmake @@ -68,41 +68,10 @@ add_custom_target( savedefconfig COMMAND ${CMAKE_COMMAND} -E env ${KCONFIG_ENV} savedefconfig --out ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND grep "CONFIG_ARCH=" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND grep "^CONFIG_ARCH_CHIP_" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "CONFIG_ARCH_CHIP=" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "CONFIG_ARCH_BOARD=" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "^CONFIG_ARCH_CUSTOM" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "^CONFIG_ARCH_BOARD_CUSTOM" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND export LC_ALL=C && cat ${CMAKE_BINARY_DIR}/defconfig.tmp | sort | uniq - > ${CMAKE_BINARY_DIR}/sortedconfig.tmp || true - COMMAND echo "\\#" > ${CMAKE_BINARY_DIR}/warning.tmp || true - COMMAND echo "\\# This file is autogenerated: PLEASE DO NOT EDIT IT." >> - ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND echo "\\#" >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND - echo - "\\# You can use \\\"make menuconfig\\\" to make any modifications to the installed .config file." - >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND - echo - "\\# You can then do \\\"make savedefconfig\\\" to generate a new defconfig file that includes your" - >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND echo "\\# modifications." >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND echo "\\#" >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND cat ${CMAKE_BINARY_DIR}/warning.tmp - ${CMAKE_BINARY_DIR}/sortedconfig.tmp > ${CMAKE_BINARY_DIR}/defconfig + COMMAND ${CMAKE_COMMAND} -P ${NUTTX_DIR}/cmake/savedefconfig.cmake + ${CMAKE_BINARY_DIR}/.config ${CMAKE_BINARY_DIR}/defconfig.tmp COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/defconfig ${NUTTX_DEFCONFIG} - COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/sortedconfig.tmp WORKING_DIRECTORY ${NUTTX_DIR}) # utility target to restore .config from board's defconfig diff --git a/cmake/nuttx_add_application.cmake b/cmake/nuttx_add_application.cmake index fc12f28518b1d..4701987c6b43f 100644 --- a/cmake/nuttx_add_application.cmake +++ b/cmake/nuttx_add_application.cmake @@ -161,6 +161,10 @@ function(nuttx_add_application) PRIVATE $>) endif() + else() + set(TARGET "apps_${NAME}") + add_custom_target(${TARGET}) + set_property(GLOBAL APPEND PROPERTY NUTTX_APPS_ONLY_REGISTER ${TARGET}) endif() # store parameters into properties (used during builtin list generation) diff --git a/cmake/savedefconfig.cmake b/cmake/savedefconfig.cmake new file mode 100644 index 0000000000000..2aa6fd6a15b0f --- /dev/null +++ b/cmake/savedefconfig.cmake @@ -0,0 +1,72 @@ +# ############################################################################## +# cmake/savedefconfig.cmake +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +include(cmake/nuttx_kconfig.cmake) + +set(SOURCE_FILE ${CMAKE_ARGV3}) +set(TARGET_FILE ${CMAKE_ARGV4}) + +file(STRINGS ${SOURCE_FILE} ConfigContents) +encode_brackets(ConfigContents) + +foreach(NameAndValue ${ConfigContents}) + decode_brackets(NameAndValue) + encode_semicolon(NameAndValue) + if("${NameAndValue}" MATCHES "CONFIG_ARCH=" + OR "${NameAndValue}" MATCHES "^CONFIG_ARCH_CHIP_" + OR "${NameAndValue}" MATCHES "CONFIG_ARCH_CHIP=" + OR "${NameAndValue}" MATCHES "CONFIG_ARCH_BOARD=" + OR "${NameAndValue}" MATCHES "^CONFIG_ARCH_CUSTOM" + OR "${NameAndValue}" MATCHES "^CONFIG_ARCH_BOARD_CUSTOM") + decode_semicolon(Value) + file(APPEND ${TARGET_FILE} "${NameAndValue}\n") + endif() +endforeach() + +get_filename_component(BINARY_DIR "${TARGET_FILE}" DIRECTORY) + +set(OUTPUT_FILE ${BINARY_DIR}/defconfig) + +# cmake-format: off +file(WRITE ${OUTPUT_FILE} "") +file(APPEND ${OUTPUT_FILE} "\#\n") +file(APPEND ${OUTPUT_FILE} "\# This file is autogenerated: PLEASE DO NOT EDIT IT.\n") +file(APPEND ${OUTPUT_FILE} "\#\n") +file(APPEND ${OUTPUT_FILE} "\# You can use \"make menuconfig\" to make any modifications to the installed .config file.\n") +file(APPEND ${OUTPUT_FILE} "\# You can then do \"make savedefconfig\" to generate a new defconfig file that includes your\n") +file(APPEND ${OUTPUT_FILE} "\# modifications.\n") +file(APPEND ${OUTPUT_FILE} "\#\n") +file(READ ${TARGET_FILE} CONTENTS) +# cmake-format: on +encode_brackets(CONTENTS) +encode_semicolon(CONTENTS) + +string(REGEX MATCHALL "[^\n]+" LINES ${CONTENTS}) + +list(REMOVE_DUPLICATES LINES) +list(SORT LINES) + +foreach(LINE IN LISTS LINES) + decode_brackets(LINE) + decode_semicolon(LINE) + file(APPEND ${OUTPUT_FILE} "${LINE}\n") +endforeach() + +execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${TARGET_FILE}) diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index d3f32ac00663f..b365491feead8 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -30,6 +30,10 @@ if(CONFIG_I2C) list(APPEND SRCS i2c_bitbang.c) endif() + if(CONFIG_I2C_SLAVE_DRIVER) + list(APPEND SRCS i2c_slave_driver.c) + endif() + # Include the selected I2C multiplexer drivers if(CONFIG_I2CMULTIPLEXER_PCA9540BDP) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 764fc7473db8f..dfa74af883c7b 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -24,6 +24,37 @@ config I2C_SLAVE bool "I2C Slave" default n +menu "I2C Slave Support" + +config I2C_SLAVE_DRIVER + bool "I2C Slave driver" + default n + ---help--- + Enable I2C Slave driver + +config I2C_SLAVE_READBUFSIZE + int "I2C Slave driver read buffer size" + default 32 + depends on I2C_SLAVE_DRIVER + ---help--- + I2C Slave read buffer size + +config I2C_SLAVE_WRITEBUFSIZE + int "I2C Slave driver write buffer size" + default 32 + depends on I2C_SLAVE_DRIVER + ---help--- + I2C Slave write buffer size + +config I2C_SLAVE_NPOLLWAITERS + int "Number of i2c slave poll waiters" + default 1 + depends on I2C_SLAVE_DRIVER + ---help--- + Number of waiters to i2c slave poll + +endmenu # I2C Slave Support + config I2C_POLLED bool "Polled I2C (no interrupts)" default n diff --git a/drivers/i2c/Make.defs b/drivers/i2c/Make.defs index d069ad80dc601..e823327de080d 100644 --- a/drivers/i2c/Make.defs +++ b/drivers/i2c/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_I2C_BITBANG),y) CSRCS += i2c_bitbang.c endif +ifeq ($(CONFIG_I2C_SLAVE_DRIVER),y) +CSRCS += i2c_slave_driver.c +endif + # Include the selected I2C multiplexer drivers ifeq ($(CONFIG_I2CMULTIPLEXER_PCA9540BDP),y) diff --git a/drivers/i2c/i2c_driver.c b/drivers/i2c/i2c_driver.c index 8e35deb98ba46..1a78a64b2d708 100644 --- a/drivers/i2c/i2c_driver.c +++ b/drivers/i2c/i2c_driver.c @@ -37,8 +37,6 @@ #include #include -#ifdef CONFIG_I2C_DRIVER - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -137,13 +135,25 @@ static int i2cdrvr_open(FAR struct file *filep) return ret; } + /* I2c master initialize */ + + if (priv->i2c->ops->setup != NULL && priv->crefs == 0) + { + ret = I2C_SETUP(priv->i2c); + if (ret < 0) + { + goto out; + } + } + /* Increment the count of open references on the driver */ priv->crefs++; DEBUGASSERT(priv->crefs > 0); +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } #endif @@ -173,6 +183,17 @@ static int i2cdrvr_close(FAR struct file *filep) return ret; } + /* I2c master uninitialize */ + + if (priv->i2c->ops->shutdown != NULL && priv->crefs == 1) + { + ret = I2C_SHUTDOWN(priv->i2c); + if (ret < 0) + { + goto out; + } + } + /* Decrement the count of open references on the driver */ DEBUGASSERT(priv->crefs > 0); @@ -189,8 +210,9 @@ static int i2cdrvr_close(FAR struct file *filep) return OK; } +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } #endif @@ -408,4 +430,3 @@ int i2c_register(FAR struct i2c_master_s *i2c, int bus) return -ENOMEM; } -#endif /* CONFIG_I2C_DRIVER */ diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c new file mode 100644 index 0000000000000..79ade78f6fb32 --- /dev/null +++ b/drivers/i2c/i2c_slave_driver.c @@ -0,0 +1,596 @@ +/**************************************************************************** + * drivers/i2c/i2c_slave_driver.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DEVNAME_FMT "/dev/i2cslv%d" +#define DEVNAME_FMTLEN (11 + 3 + 1) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int i2c_slave_open(FAR struct file *filep); +static int i2c_slave_close(FAR struct file *filep); +static ssize_t i2c_slave_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t i2c_slave_write(FAR struct file *filep, + FAR const char *buffer, size_t buflen); +static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int i2c_slave_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct i2c_slave_driver_s +{ + /* Slave private data */ + + FAR struct i2c_slave_s *dev; + + /* Slave send buffer */ + + uint8_t write_buffer[CONFIG_I2C_SLAVE_WRITEBUFSIZE]; + + /* Slave receive buffer */ + + uint8_t read_buffer[CONFIG_I2C_SLAVE_READBUFSIZE]; + + /* Slave receive buffer length */ + + size_t read_length; + + /* Read buffer index */ + + size_t read_index; + + /* Wait for transfer to complete */ + + sem_t wait; + + /* I2C Slave write flag */ + + bool writeable; + + /* Mutual exclusion */ + + mutex_t lock; + + /* The poll waiter */ + + FAR struct pollfd *fds[CONFIG_I2C_SLAVE_NPOLLWAITERS]; + + /* Number of open references */ + + int16_t crefs; + + /* I2C Slave address */ + + int addr; + + /* The number of address bits provided (7 or 10) */ + + int nbits; + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + bool unlinked; /* Indicates if the driver has been unlinked */ +#endif +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_i2cslavefops = +{ + i2c_slave_open, /* open */ + i2c_slave_close, /* close */ + i2c_slave_read, /* read */ + i2c_slave_write, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* truncate */ + i2c_slave_poll /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , i2c_slave_unlink /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2c_slave_open + * + * Description: + * This function is called whenever the I2C Slave device is opened. + * + * Input Parameters: + * filep - File structure instance + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +static int i2c_slave_open(FAR struct file *filep) +{ + FAR struct i2c_slave_driver_s *priv; + int ret; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + /* I2c slave initialize */ + + if (priv->dev->ops->setup != NULL && priv->crefs == 0) + { + ret = I2CS_SETUP(priv->dev); + if (ret < 0) + { + goto out; + } + } + + /* Set i2c slave address */ + + ret = I2CS_SETOWNADDRESS(priv->dev, priv->addr, priv->nbits); + if (ret < 0) + { + if (priv->dev->ops->shutdown != NULL) + { + ret = I2CS_SHUTDOWN(priv->dev); + } + } + + /* Increment the count of open references on the driver */ + + priv->crefs++; + DEBUGASSERT(priv->crefs > 0); + +out: + nxmutex_unlock(&priv->lock); + return ret; +} + +/**************************************************************************** + * Name: i2c_slave_close + * + * Description: + * This routine is called when the I2C Slave device is closed. + * + * Input Parameters: + * filep - File structure instance + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +static int i2c_slave_close(FAR struct file *filep) +{ + FAR struct i2c_slave_driver_s *priv; + int ret = OK; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C slave driver state structure */ + + nxmutex_lock(&priv->lock); + + /* I2c slave uninitialize */ + + if (priv->dev->ops->shutdown != NULL && priv->crefs == 1) + { + ret = I2CS_SHUTDOWN(priv->dev); + if (ret < 0) + { + goto out; + } + } + + /* Decrement the count of open references on the driver */ + + DEBUGASSERT(priv->crefs > 0); + priv->crefs--; +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + if (priv->crefs <= 0 && priv->unlinked) + { + nxmutex_destroy(&priv->lock); + kmm_free(priv); + filep->f_inode->i_private = NULL; + return OK; + } +#endif + +out: + nxmutex_unlock(&priv->lock); + return ret; +} + +/**************************************************************************** + * Name: i2c_slave_read + * + * Description: + * This routine is called when the application requires to read the data + * received by the I2C Slave device. + * + * Input Parameters: + * filep - File structure instance + * buffer - User-provided to save the data + * buflen - The maximum size of the user-provided buffer + * + * Returned Value: + * The positive non-zero number of bytes read on success, 0 on if an + * end-of-file condition, or a negated errno value on any failure. + * + ****************************************************************************/ + +static ssize_t i2c_slave_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct i2c_slave_driver_s *priv; + int ret; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + while (priv->read_length == 0) + { + nxmutex_unlock(&priv->lock); + if (filep->f_oflags & O_NONBLOCK) + { + return -EAGAIN; + } + + ret = nxsem_wait(&priv->wait); + if (ret < 0) + { + return ret; + } + + nxmutex_lock(&priv->lock); + } + + buflen = MIN(buflen, priv->read_length); + memcpy(buffer, priv->read_buffer + priv->read_index, buflen); + priv->read_index += buflen; + priv->read_length -= buflen; + nxmutex_unlock(&priv->lock); + return buflen; +} + +/**************************************************************************** + * Name: i2c_slave_write + * + * Description: + * This routine is called when the application needs to enqueue data to be + * transferred at the next leading clock edge of the I2C Slave controller. + * + * Input Parameters: + * filep - Instance of struct file to use with the write + * buffer - Data to write + * buflen - Length of data to write in bytes + * + * Returned Value: + * On success, the number of bytes written are returned (zero indicates + * nothing was written). On any failure, a negated errno value is returned. + * + ****************************************************************************/ + +static ssize_t i2c_slave_write(FAR struct file *filep, + FAR const char *buffer, size_t buflen) +{ + FAR struct i2c_slave_driver_s *priv; + size_t write_bytes; + int ret; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + write_bytes = MIN(buflen, CONFIG_I2C_SLAVE_WRITEBUFSIZE); + memcpy(priv->write_buffer, buffer, write_bytes); + ret = I2CS_WRITE(priv->dev, priv->write_buffer, write_bytes); + if (ret >= 0) + { + priv->writeable = false; + } + + nxmutex_unlock(&priv->lock); + return ret < 0 ? ret : write_bytes; +} + +/**************************************************************************** + * Name: i2c_slave_poll + ****************************************************************************/ + +static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct i2c_slave_driver_s *priv; + int ret = OK; + int i; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + if (setup) + { + pollevent_t eventset = 0; + + for (i = 0; i < CONFIG_I2C_SLAVE_NPOLLWAITERS; i++) + { + if (!priv->fds[i]) + { + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i == CONFIG_I2C_SLAVE_NPOLLWAITERS) + { + ret = -EBUSY; + goto out; + } + + if (priv->read_length > 0) + { + eventset |= POLLIN; + } + + if (priv->writeable) + { + eventset |= POLLOUT; + } + + poll_notify(priv->fds, CONFIG_I2C_SLAVE_NPOLLWAITERS, eventset); + } + else if (fds->priv != NULL) + { + struct pollfd **slot = fds->priv; + *slot = NULL; + fds->priv = NULL; + } + +out: + nxmutex_unlock(&priv->lock); + return ret; +} + +/**************************************************************************** + * Name: i2c_slave_unlink + * + * Description: + * This routine is called when the I2C Slave device is unlinked. + * + * Input Parameters: + * inode - The inode associated with the I2C Slave device + * + * Returned Value: + * Zero is returned on success; a negated value is returned on any failure. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int i2c_slave_unlink(FAR struct inode *inode) +{ + FAR struct i2c_slave_driver_s *priv; + + DEBUGASSERT(inode->i_private != NULL); + + /* Get our private data structure */ + + priv = inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + /* Are there open references to the driver data structure? */ + + if (priv->crefs <= 0) + { + nxmutex_destroy(&priv->lock); + kmm_free(priv); + inode->i_private = NULL; + return OK; + } + + /* No... just mark the driver as unlinked and free the resources when the + * last client closes their reference to the driver. + */ + + priv->unlinked = true; + nxmutex_unlock(&priv->lock); + return OK; +} +#endif + +static int i2c_slave_callback(FAR void *arg, i2c_slave_complete_t status, + size_t length) +{ + FAR struct i2c_slave_driver_s *priv = arg; + pollevent_t events; + int semcount; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + if (status == I2CS_RX_COMPLETE) + { + events = POLLIN; + priv->read_index = 0; + priv->read_length = length; + + while (nxsem_get_value(&priv->wait, &semcount) >= 0 && semcount <= 1) + { + nxsem_post(&priv->wait); + } + } + else + { + events = POLLOUT; + priv->writeable = true; + } + + nxmutex_unlock(&priv->lock); + poll_notify(priv->fds, CONFIG_I2C_SLAVE_NPOLLWAITERS, events); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2c_slave_register + * + * Description: + * Register the I2C Slave character device driver as 'devpath'. + * + * Input Parameters: + * dev - An instance of the I2C Slave interface to use to communicate + * with the I2C Slave device + * bus - The I2C Slave bus number. This will be used as the I2C device + * minor number. The I2C Slave character device will be + * registered as /dev/i2cslvN where N is the minor number + * addr - I2C Slave address + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, + int nbits) +{ + FAR struct i2c_slave_driver_s *priv; + char devname[DEVNAME_FMTLEN]; + int ret; + + /* Sanity check */ + + DEBUGASSERT(dev != NULL && (unsigned int)bus < 1000); + + priv = kmm_zalloc(sizeof(struct i2c_slave_driver_s)); + if (priv == NULL) + { + return -ENOMEM; + } + + snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, bus); + ret = register_driver(devname, &g_i2cslavefops, 0666, priv); + if (ret < 0) + { + kmm_free(priv); + return ret; + } + + nxsem_init(&priv->wait, 0, 0); + nxmutex_init(&priv->lock); + priv->dev = dev; + priv->addr = addr; + priv->nbits = nbits; + priv->writeable = true; + + ret = I2CS_READ(priv->dev, priv->read_buffer, + CONFIG_I2C_SLAVE_READBUFSIZE); + if (ret < 0) + { + goto out; + } + + ret = I2CS_REGISTERCALLBACK(priv->dev, i2c_slave_callback, priv); + if (ret >= 0) + { + return OK; + } + +out: + nxmutex_destroy(&priv->lock); + nxsem_destroy(&priv->wait); + unregister_driver(devname); + kmm_free(priv); + return ret; +} diff --git a/drivers/i2c/pca9540bdp.c b/drivers/i2c/pca9540bdp.c index a83c318279967..321635c204973 100644 --- a/drivers/i2c/pca9540bdp.c +++ b/drivers/i2c/pca9540bdp.c @@ -36,8 +36,6 @@ #include "pca9540bdp.h" #include -#ifdef CONFIG_I2CMULTIPLEXER_PCA9540BDP - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -299,4 +297,3 @@ FAR struct pca9540bdp_dev_s * return priv; } -#endif /* CONFIG_I2CMULTIPLEXER_PCA9540BDP */ diff --git a/drivers/i2c/tca9548a.c b/drivers/i2c/tca9548a.c index ae2ddfa758a23..e4ad72228a252 100644 --- a/drivers/i2c/tca9548a.c +++ b/drivers/i2c/tca9548a.c @@ -36,8 +36,6 @@ #include #include -#ifdef CONFIG_I2CMULTIPLEXER_TCA9548A - #ifndef CONFIG_TCA9548A_I2C_FREQUENCY # define CONFIG_TCA9548A_I2C_FREQUENCY 400000 #endif @@ -409,4 +407,3 @@ FAR struct tca9548a_dev_s * return priv; } -#endif /* CONFIG_I2CMULTIPLEXER_TCA9548A */ diff --git a/drivers/input/touchscreen_upper.c b/drivers/input/touchscreen_upper.c index b85930dab9d3e..18e5471c2244f 100644 --- a/drivers/input/touchscreen_upper.c +++ b/drivers/input/touchscreen_upper.c @@ -61,6 +61,7 @@ struct touch_upperhalf_s mutex_t lock; /* Manages exclusive access to this structure */ struct list_node head; /* Opened file buffer chain header node */ FAR struct touch_lowerhalf_s *lower; /* A pointer of lower half instance */ + FAR struct touch_openpriv_s *grab; /* A pointer of grab file */ }; /**************************************************************************** @@ -78,6 +79,9 @@ static int touch_ioctl(FAR struct file *filep, int cmd, static int touch_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); +static void touch_event_notify(FAR struct touch_openpriv_s *openpriv, + FAR const struct touch_sample_s *sample); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -163,6 +167,11 @@ static int touch_close(FAR struct file *filep) return ret; } + if (upper->grab == openpriv) + { + upper->grab = NULL; + } + list_delete(&openpriv->node); circbuf_uninit(&openpriv->circbuf); nxsem_destroy(&openpriv->waitsem); @@ -250,9 +259,10 @@ static ssize_t touch_read(FAR struct file *filep, FAR char *buffer, static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - FAR struct inode *inode = filep->f_inode; - FAR struct touch_upperhalf_s *upper = inode->i_private; - FAR struct touch_lowerhalf_s *lower = upper->lower; + FAR struct touch_openpriv_s *openpriv = filep->f_priv; + FAR struct inode *inode = filep->f_inode; + FAR struct touch_upperhalf_s *upper = inode->i_private; + FAR struct touch_lowerhalf_s *lower = upper->lower; int ret; ret = nxmutex_lock(&upper->lock); @@ -261,13 +271,48 @@ static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) return ret; } - if (lower->control) - { - ret = lower->control(lower, cmd, arg); - } - else + switch (cmd) { - ret = -ENOTTY; + case TSIOC_GRAB: + { + int enable = (int)arg; + ret = OK; + if (enable) + { + if (upper->grab != NULL) + { + ret = -EBUSY; + } + else + { + upper->grab = openpriv; + } + } + else + { + if (upper->grab != openpriv) + { + ret = -EINVAL; + } + else + { + upper->grab = NULL; + } + } + } + break; + default: + { + if (lower->control) + { + ret = lower->control(lower, cmd, arg); + } + else + { + ret = -ENOTTY; + } + } + break; } nxmutex_unlock(&upper->lock); @@ -321,6 +366,27 @@ static int touch_poll(FAR struct file *filep, struct pollfd *fds, bool setup) return ret; } +/**************************************************************************** + * Name: touch_event_notify + ****************************************************************************/ + +static void touch_event_notify(FAR struct touch_openpriv_s *openpriv, + FAR const struct touch_sample_s *sample) +{ + int semcount; + + circbuf_overwrite(&openpriv->circbuf, sample, + SIZEOF_TOUCH_SAMPLE_S(sample->npoints)); + + nxsem_get_value(&openpriv->waitsem, &semcount); + if (semcount < 1) + { + nxsem_post(&openpriv->waitsem); + } + + poll_notify(&openpriv->fds, 1, POLLIN); +} + /**************************************************************************** * Public Function ****************************************************************************/ @@ -333,25 +399,23 @@ void touch_event(FAR void *priv, FAR const struct touch_sample_s *sample) { FAR struct touch_upperhalf_s *upper = priv; FAR struct touch_openpriv_s *openpriv; - int semcount; if (nxmutex_lock(&upper->lock) < 0) { return; } - list_for_every_entry(&upper->head, openpriv, struct touch_openpriv_s, node) + if (upper->grab) { - circbuf_overwrite(&openpriv->circbuf, sample, - SIZEOF_TOUCH_SAMPLE_S(sample->npoints)); - - nxsem_get_value(&openpriv->waitsem, &semcount); - if (semcount < 1) + touch_event_notify(upper->grab, sample); + } + else + { + list_for_every_entry(&upper->head, openpriv, + struct touch_openpriv_s, node) { - nxsem_post(&openpriv->waitsem); + touch_event_notify(openpriv, sample); } - - poll_notify(&openpriv->fds, 1, POLLIN); } nxmutex_unlock(&upper->lock); diff --git a/drivers/mtd/mtd_nandram.c b/drivers/mtd/mtd_nandram.c index cfaaef7366ed4..a2b96744166fd 100644 --- a/drivers/mtd/mtd_nandram.c +++ b/drivers/mtd/mtd_nandram.c @@ -25,6 +25,7 @@ * Included Files ****************************************************************************/ +#include #include #include @@ -89,8 +90,8 @@ #else -#define NAND_RAM_LOG -#define NAND_RAM_STATUS_LOG +#define NAND_RAM_LOG(str, ...) +#define NAND_RAM_STATUS_LOG(str, ...) #endif /* CONFIG_MTD_NAND_RAM_DEBUG */ @@ -197,10 +198,12 @@ static void nand_ram_storage_status(void) static inline void nand_ram_status(void) { +#ifdef CONFIG_MTD_NAND_RAM_DEBUG if (nand_ram_ins_i % NAND_RAM_STATUS_LEVEL == 0) { nand_ram_storage_status(); } +#endif } /**************************************************************************** @@ -353,12 +356,19 @@ int nand_ram_rawread(FAR struct nand_raw_s *raw, off_t block, if (data != NULL) { - memcpy(data, (const void *)read_page_data, NAND_RAM_PAGE_SIZE); + if (nand_ram_flash_spare[read_page].free == NAND_RAM_PAGE_FREE) + { + memset(data, 0, NAND_RAM_PAGE_SIZE); + } + else + { + memcpy(data, (const void *)read_page_data, NAND_RAM_PAGE_SIZE); + } } if (spare != NULL) { - memcpy(spare, (const void *)read_page_spare, NAND_RAM_PAGE_SIZE); + memcpy(spare, (const void *)read_page_spare, NAND_RAM_SPARE_SIZE); } NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "rawread"); @@ -420,6 +430,7 @@ int nand_ram_rawwrite(FAR struct nand_raw_s *raw, off_t block, nand_ram_flash_spare[write_page].n_write++; + memset((void *)write_page_data, 0, NAND_RAM_PAGE_SIZE); if (data != NULL) { memcpy((void *)write_page_data, data, NAND_RAM_PAGE_SIZE); diff --git a/drivers/mtd/mtd_nandwrapper.c b/drivers/mtd/mtd_nandwrapper.c index 83e6bbc9862d9..4c84340069aa9 100644 --- a/drivers/mtd/mtd_nandwrapper.c +++ b/drivers/mtd/mtd_nandwrapper.c @@ -328,7 +328,7 @@ int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block) nxmutex_lock(&nand_wrapper_dev_mut); nand_wrapper_ins_i++; - NAND_WRAPPER_LOG("[UPPER %lu | %s] Blocks: %d\n", + NAND_WRAPPER_LOG("[UPPER %lu | %s] Block: %d\n", nand_wrapper_ins_i, "isbad", block); DEBUGASSERT(nand_dev && nand_dev->under.mtd.isbad); @@ -336,8 +336,8 @@ int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block) if (ret >= 0) { - NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n", - nand_wrapper_ins_i, "isbad"); + NAND_WRAPPER_LOG("[UPPER %lu | %s] Done %d\n", + nand_wrapper_ins_i, "isbad", ret); } else { diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index 3f55c31584b21..bbd5b9e53fa2c 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -330,8 +330,8 @@ static int net_rpmsg_drv_sockioctl_task(int argc, FAR char *argv[]) /* Restore pointers from argv */ - ept = (FAR struct rpmsg_endpoint *)strtoul(argv[1], NULL, 0); - msg = (FAR struct net_rpmsg_ioctl_s *)strtoul(argv[2], NULL, 0); + ept = (FAR struct rpmsg_endpoint *)strtoul(argv[1], NULL, 16); + msg = (FAR struct net_rpmsg_ioctl_s *)strtoul(argv[2], NULL, 16); /* We need a temporary sock for ioctl here */ diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9a81cd7e10609..9d84b959daee5 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -969,9 +969,8 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { FAR struct tun_device_s *priv = filep->f_priv; - ssize_t nwritten = 0; uint8_t llhdrlen; - int ret; + ssize_t ret; if (priv == NULL || buflen > CONFIG_NET_TUN_PKTSIZE) { @@ -989,7 +988,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, ret = nxmutex_lock(&priv->lock); if (ret < 0) { - return nwritten == 0 ? (ssize_t)ret : nwritten; + return ret; } /* Check if there are free space to write */ @@ -1002,7 +1001,6 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, priv->dev.d_buf = NULL; if (ret < 0) { - nwritten = (nwritten == 0) ? ret : nwritten; net_unlock(); break; } @@ -1011,7 +1009,6 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, buflen, -llhdrlen, false); if (ret < 0) { - nwritten = (nwritten == 0) ? ret : nwritten; net_unlock(); break; } @@ -1021,7 +1018,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, tun_net_receive(priv); net_unlock(); - nwritten = buflen; + ret = buflen; break; } @@ -1029,7 +1026,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, if ((filep->f_oflags & O_NONBLOCK) != 0) { - nwritten = -EAGAIN; + ret = -EAGAIN; break; } @@ -1039,7 +1036,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, } nxmutex_unlock(&priv->lock); - return nwritten; + return ret; } /**************************************************************************** @@ -1050,9 +1047,8 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { FAR struct tun_device_s *priv = filep->f_priv; - ssize_t nread = 0; uint8_t llhdrlen; - int ret; + ssize_t ret; if (priv == NULL) { @@ -1070,7 +1066,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, ret = nxmutex_lock(&priv->lock); if (ret < 0) { - return nread == 0 ? (ssize_t)ret : nread; + return ret; } /* Check if there are data to read in write buffer */ @@ -1079,13 +1075,13 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, { if (buflen < priv->write_d_len) { - nread = -EINVAL; + ret = -EINVAL; break; } iob_copyout((FAR uint8_t *)buffer, priv->write_buf, priv->write_d_len, -llhdrlen); - nread = priv->write_d_len; + ret = priv->write_d_len; iob_free_chain(priv->write_buf); priv->write_buf = NULL; @@ -1102,13 +1098,13 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, { if (buflen < priv->read_d_len) { - nread = -EINVAL; + ret = -EINVAL; break; } iob_copyout((FAR uint8_t *)buffer, priv->read_buf, priv->read_d_len, -llhdrlen); - nread = priv->read_d_len; + ret = priv->read_d_len; iob_free_chain(priv->read_buf); priv->read_buf = NULL; @@ -1124,7 +1120,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, if ((filep->f_oflags & O_NONBLOCK) != 0) { - nread = -EAGAIN; + ret = -EAGAIN; break; } @@ -1134,7 +1130,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, } nxmutex_unlock(&priv->lock); - return nread; + return ret; } /**************************************************************************** diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 6c78c06bc28d5..6abab708aa08e 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -379,6 +379,23 @@ config SENSORS_BMP280 if SENSORS_BMP280 +choice + prompt "I2C Address" + default BMP280_I2C_ADDR_76 + +config BMP280_I2C_ADDR_76 + bool "0x76" + ---help--- + Default address. + If SDO pin is pulled to GND, use 0x76 + +config BMP280_I2C_ADDR_77 + bool "0x77" + ---help--- + If SDO pin is pulled to VDDIO, use 0x77 + +endchoice # I2C Address + config BMP280_I2C_FREQUENCY int "BMP280 I2C frequency" default 400000 diff --git a/drivers/sensors/bmp280_uorb.c b/drivers/sensors/bmp280_uorb.c index 7acdb664d9362..ecf5289d86472 100644 --- a/drivers/sensors/bmp280_uorb.c +++ b/drivers/sensors/bmp280_uorb.c @@ -42,7 +42,11 @@ * Pre-processor Definitions ****************************************************************************/ +#ifdef CONFIG_BMP280_I2C_ADDR_76 #define BMP280_ADDR 0x76 +#else +#define BMP280_ADDR 0x77 +#endif #define BMP280_FREQ CONFIG_BMP280_I2C_FREQUENCY #define DEVID 0x58 diff --git a/drivers/sensors/goldfish_gps_uorb.c b/drivers/sensors/goldfish_gps_uorb.c index 766d7faea0eb2..a59cf0bf3d192 100644 --- a/drivers/sensors/goldfish_gps_uorb.c +++ b/drivers/sensors/goldfish_gps_uorb.c @@ -142,7 +142,7 @@ static int goldfish_gps_activate(FAR struct gps_lowerhalf_s *gps, static int goldfish_gps_thread(int argc, FAR char** argv) { FAR struct goldfish_gps_s *priv = (FAR struct goldfish_gps_s *) - ((uintptr_t)strtoul(argv[1], NULL, 0)); + ((uintptr_t)strtoul(argv[1], NULL, 16)); ssize_t len; char buf[256]; diff --git a/drivers/sensors/goldfish_sensor_uorb.c b/drivers/sensors/goldfish_sensor_uorb.c index 94b7550d994d9..a61f98cfe2102 100644 --- a/drivers/sensors/goldfish_sensor_uorb.c +++ b/drivers/sensors/goldfish_sensor_uorb.c @@ -588,7 +588,7 @@ static int goldfish_sensor_activate(FAR struct sensor_lowerhalf_s *lower, static int goldfish_sensor_thread(int argc, FAR char** argv) { FAR struct goldfish_sensor_s *priv = - (FAR struct goldfish_sensor_s *)((uintptr_t)strtoul(argv[1], NULL, 0)); + (FAR struct goldfish_sensor_s *)((uintptr_t)strtoul(argv[1], NULL, 16)); while (true) { diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 94b40dfe4c0b4..953cb22af5338 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -35,8 +35,6 @@ #include -#ifdef CONFIG_SPI_BITBANG - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -559,4 +557,3 @@ void spi_destroy_bitbang(FAR struct spi_dev_s *dev) kmm_free(dev); } -#endif /* CONFIG_SPI_BITBANG */ diff --git a/drivers/spi/spi_driver.c b/drivers/spi/spi_driver.c index ec1ae8a90c1b0..0774dcd956eba 100644 --- a/drivers/spi/spi_driver.c +++ b/drivers/spi/spi_driver.c @@ -37,8 +37,6 @@ #include #include -#ifdef CONFIG_SPI_DRIVER - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -118,16 +116,16 @@ static const struct file_operations g_spidrvr_fops = #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int spidrvr_open(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_driver_s *priv; int ret; - /* Get our private data structure */ + /* Sanity check */ - inode = filep->f_inode; + DEBUGASSERT(filep->f_inode->i_private != NULL); - priv = inode->i_private; - DEBUGASSERT(priv); + /* Get our private data structure */ + + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI driver state structure */ @@ -154,16 +152,16 @@ static int spidrvr_open(FAR struct file *filep) #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int spidrvr_close(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_driver_s *priv; int ret; - /* Get our private data structure */ + /* Sanity check */ - inode = filep->f_inode; + DEBUGASSERT(filep->f_inode->i_private != NULL); - priv = inode->i_private; - DEBUGASSERT(priv); + /* Get our private data structure */ + + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI driver state structure */ @@ -186,6 +184,7 @@ static int spidrvr_close(FAR struct file *filep) { nxmutex_destroy(&priv->lock); kmm_free(priv); + filep->f_inode->i_private = NULL; return OK; } @@ -220,19 +219,18 @@ static ssize_t spidrvr_write(FAR struct file *filep, FAR const char *buffer, static int spidrvr_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - FAR struct inode *inode; FAR struct spi_driver_s *priv; FAR struct spi_sequence_s *seq; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("cmd=%d arg=%lu\n", cmd, arg); /* Get our private data structure */ - inode = filep->f_inode; - - priv = inode->i_private; - DEBUGASSERT(priv); + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI driver state structure */ @@ -307,6 +305,7 @@ static int spidrvr_unlink(FAR struct inode *inode) { nxmutex_destroy(&priv->lock); kmm_free(priv); + inode->i_private = NULL; return OK; } @@ -393,4 +392,3 @@ int spi_register(FAR struct spi_dev_s *spi, int bus) return -ENOMEM; } -#endif /* CONFIG_SPI_DRIVER */ diff --git a/drivers/spi/spi_slave_driver.c b/drivers/spi/spi_slave_driver.c index d23fadf14ac4f..1e33b4f242e10 100644 --- a/drivers/spi/spi_slave_driver.c +++ b/drivers/spi/spi_slave_driver.c @@ -106,7 +106,10 @@ static ssize_t spi_slave_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); static int spi_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int spi_slave_unlink(FAR struct inode *inode); +#endif /* SPI Slave driver methods */ @@ -171,18 +174,17 @@ static const struct spi_slave_devops_s g_spisdev_ops = static int spi_slave_open(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; int ret; - DEBUGASSERT(filep->f_inode->i_private != NULL); + /* Sanity check */ + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep: %p\n", filep); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI Slave driver state structure */ @@ -226,18 +228,17 @@ static int spi_slave_open(FAR struct file *filep) static int spi_slave_close(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; int ret; - DEBUGASSERT(filep->f_inode->i_private != NULL); + /* Sanity check */ + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep: %p\n", filep); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI Slave driver state structure */ @@ -270,7 +271,7 @@ static int spi_slave_close(FAR struct file *filep) { nxmutex_destroy(&priv->lock); kmm_free(priv); - inode->i_private = NULL; + filep->f_inode->i_private = NULL; return OK; } @@ -299,18 +300,19 @@ static int spi_slave_close(FAR struct file *filep) static ssize_t spi_slave_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; size_t read_bytes; size_t remaining_words; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep=%p buffer=%p buflen=%zu\n", filep, buffer, buflen); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; if (buffer == NULL) { @@ -391,17 +393,18 @@ static ssize_t spi_slave_read(FAR struct file *filep, FAR char *buffer, static ssize_t spi_slave_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; size_t enqueued_bytes; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep=%p buffer=%p buflen=%zu\n", filep, buffer, buflen); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; ret = nxmutex_lock(&priv->lock); if (ret < 0) @@ -450,13 +453,15 @@ static int spi_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) { FAR struct spi_slave_driver_s *priv; - FAR struct inode *inode; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); + /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; ret = nxmutex_lock(&priv->lock); if (ret < 0) @@ -522,6 +527,8 @@ static int spi_slave_unlink(FAR struct inode *inode) FAR struct spi_slave_driver_s *priv; int ret; + /* Sanity check */ + DEBUGASSERT(inode->i_private != NULL); /* Get our private data structure */ diff --git a/drivers/spi/spi_transfer.c b/drivers/spi/spi_transfer.c index 82d1e70c61f89..4b93d3148ca02 100644 --- a/drivers/spi/spi_transfer.c +++ b/drivers/spi/spi_transfer.c @@ -33,8 +33,6 @@ #include #include -#ifdef CONFIG_SPI_EXCHANGE - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -143,4 +141,3 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct spi_sequence_s *seq) return ret; } -#endif /* CONFIG_SPI_EXCHANGE */ diff --git a/fs/CMakeLists.txt b/fs/CMakeLists.txt index 57e0fb19e0a75..cc876d4c17b5f 100644 --- a/fs/CMakeLists.txt +++ b/fs/CMakeLists.txt @@ -19,4 +19,5 @@ # ############################################################################## nuttx_add_kernel_library(fs fs_initialize.c) nuttx_add_subdirectory() -target_include_directories(fs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(fs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${NUTTX_DIR}/sched) diff --git a/fs/mnemofs/mnemofs.c b/fs/mnemofs/mnemofs.c index 2009098fa3a4a..5cf0c0fef80ae 100644 --- a/fs/mnemofs/mnemofs.c +++ b/fs/mnemofs/mnemofs.c @@ -120,25 +120,25 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer, static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence); static int mnemofs_ioctl(FAR struct file *filep, int cmd, - unsigned long arg); + unsigned long arg); static int mnemofs_truncate(FAR struct file *filep, off_t length); static int mnemofs_sync(FAR struct file *filep); static int mnemofs_dup(FAR const struct file *oldp, - FAR struct file *newp); + FAR struct file *newp); static int mnemofs_fstat(FAR const struct file *filep, - FAR struct stat *buf); + FAR struct stat *buf); static int mnemofs_opendir(FAR struct inode *mountpt, - FAR const char *relpath, - FAR struct fs_dirent_s **dir); + FAR const char *relpath, + FAR struct fs_dirent_s **dir); static int mnemofs_closedir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); static int mnemofs_readdir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir, - FAR struct dirent *entry); + FAR struct fs_dirent_s *dir, + FAR struct dirent *entry); static int mnemofs_rewinddir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); + FAR struct fs_dirent_s *dir); static int mnemofs_bind(FAR struct inode *driver, FAR const void *data, FAR void** handle); @@ -151,9 +151,9 @@ static int mnemofs_statfs(FAR struct inode *mountpt, static int mnemofs_unlink(FAR struct inode *mountpt, FAR const char *relpath); static int mnemofs_mkdir(FAR struct inode *mountpt, - FAR const char *relpath, mode_t mode); + FAR const char *relpath, mode_t mode); static int mnemofs_rmdir(FAR struct inode *mountpt, - FAR const char *relpath); + FAR const char *relpath); static int mnemofs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, FAR const char *newrelpath); @@ -250,11 +250,11 @@ const struct mountpt_operations g_mnemofs_operations = static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, int oflags, mode_t mode) { - int ret = OK; - int flags; - struct mfs_pitr_s pitr; + int ret = OK; + int flags; FAR const char *child = NULL; FAR struct inode *inode; + struct mfs_pitr_s pitr; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; FAR struct mfs_ocom_s *fcom; @@ -298,7 +298,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, /* Check creation flags. */ flags = mfs_get_patharr(sb, relpath, &f->com->path, &f->com->depth); - if ((flags & MFS_NEXIST) != 0) + if ((flags & MFS_EXIST) == 0) { if ((flags & MFS_P_ISDIR) != 0) { @@ -307,8 +307,10 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, /* Add direntry to parent's directory file. */ f->com->new_ent = true; + mfs_pitr_init(sb, f->com->path, f->com->depth, &pitr, true); child = mfs_path2childname(relpath); + finfo("Child is: %s.", child); mfs_pitr_appendnew(sb, f->com->path, f->com->depth, &pitr, child, mode); mfs_pitr_free(&pitr); @@ -347,7 +349,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, /* TODO: Update mtime and atime. */ mfs_pitr_init(sb, f->com->path, f->com->depth, &pitr, true); - mfs_pitr_readdirent(sb, &pitr, &dirent); + mfs_pitr_readdirent(sb, f->com->path, &pitr, &dirent); if (dirent != NULL) { @@ -367,7 +369,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, mfs_pitr_free(&pitr); - finfo("Direntry is read and processed."); + finfo("Direntry processing done."); /* Check Offset flags. */ @@ -378,8 +380,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, * then it's truncated. Else, the truncate flag is ignored. */ - ret = mfs_lru_del(sb, 0, f->com->sz, f->com->sz, f->com->path, - f->com->depth); + ret = mfs_lru_del(sb, 0, f->com->sz, f->com->path, f->com->depth); if (predict_false(ret < 0)) { finfo("Error while truncating file. Ret: %d.", ret); @@ -392,8 +393,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, f->com->off = f->com->sz; } - finfo("Offset flags are set."); - + finfo("[TMP1] %p %p", &sb->of, &f->list); list_add_tail(&sb->of, &f->list); filep->f_priv = f; @@ -446,7 +446,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, static int mnemofs_close(FAR struct file *filep) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -471,7 +471,7 @@ static int mnemofs_close(FAR struct file *filep) /* Flushing in-memory data to on-flash journal. */ - ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth, f->com->sz); + ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth); if (predict_false(ret < 0)) { finfo("Error while flushing file. Ret: %d.", ret); @@ -480,17 +480,18 @@ static int mnemofs_close(FAR struct file *filep) f->com->refcount--; - if (predict_true(f->com->refcount != 0)) + if (f->com->refcount == 0) { kmm_free(f->com->path); kmm_free(f->com); - kmm_free(f); finfo("Refcount is 0, open file structure freed."); } list_delete(&f->list); + kmm_free(f); filep->f_priv = NULL; + finfo("File entry removed from the open files list."); errout_with_lock: @@ -530,7 +531,7 @@ static int mnemofs_close(FAR struct file *filep) static ssize_t mnemofs_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { - int ret = 0; + int ret = 0; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -643,8 +644,8 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer, /* Write data to CTZ at the current offset. */ - ret = mfs_lru_wr(sb, f->com->off, buflen, f->com->sz, f->com->path, - f->com->depth, buffer); + ret = mfs_lru_wr(sb, f->com->off, buflen, f->com->path, f->com->depth, + buffer); if (ret < 0) { goto errout_with_lock; @@ -693,8 +694,8 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer, static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence) { - int ret = OK; - mfs_t pos; + int ret = OK; + mfs_t pos; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -782,7 +783,7 @@ static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence) static int mnemofs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct inode *drv; FAR struct mfs_sb_s *sb; @@ -844,7 +845,7 @@ static int mnemofs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) static int mnemofs_truncate(FAR struct file *filep, off_t length) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -869,8 +870,8 @@ static int mnemofs_truncate(FAR struct file *filep, off_t length) if (length < f->com->sz) { - ret = mfs_lru_del(sb, length, f->com->sz - length, f->com->sz, - f->com->path, f->com->depth); + ret = mfs_lru_del(sb, length, f->com->sz - length, f->com->path, + f->com->depth); if (predict_false(ret < 0)) { finfo("Error during truncate. Ret: %d.", ret); @@ -932,7 +933,7 @@ static int mnemofs_sync(FAR struct file *filep) f = filep->f_priv; DEBUGASSERT(f != NULL); - ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth, f->com->sz); + ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth); nxmutex_unlock(&MFS_LOCK(sb)); finfo("Lock released."); @@ -966,7 +967,7 @@ static int mnemofs_sync(FAR struct file *filep) static int mnemofs_dup(FAR const struct file *oldp, FAR struct file *newp) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *of; @@ -1055,8 +1056,8 @@ static int mnemofs_dup(FAR const struct file *oldp, FAR struct file *newp) static int mnemofs_fstat(FAR const struct file *filep, FAR struct stat *buf) { - int ret = OK; - struct mfs_pitr_s pitr; + int ret = OK; + struct mfs_pitr_s pitr; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -1081,9 +1082,10 @@ static int mnemofs_fstat(FAR const struct file *filep, FAR struct stat *buf) DEBUGASSERT(f != NULL); mfs_pitr_init(sb, f->com->path, f->com->depth, &pitr, true); - mfs_pitr_adv_tochild(&pitr, f->com->path, f->com->depth); - mfs_pitr_readdirent(sb, &pitr, &dirent); + mfs_pitr_adv_tochild(&pitr, f->com->path); + mfs_pitr_readdirent(sb, f->com->path, &pitr, &dirent); mfs_pitr_free(&pitr); + DEBUGASSERT(dirent != NULL); buf->st_mode = dirent->mode; @@ -1169,11 +1171,17 @@ static int mnemofs_opendir(FAR struct inode *mountpt, goto errout_with_lock; } + ret = mfs_lru_updatedinfo(sb, path, depth); + if (predict_false(ret < 0)) + { + goto errout_with_path; + } + pitr = kmm_zalloc(sizeof(*pitr)); if (predict_false(pitr == NULL)) { ret = -ENOMEM; - goto errout_with_lock; + goto errout_with_path; } fsdirent = kmm_zalloc(sizeof(*fsdirent)); @@ -1183,7 +1191,12 @@ static int mnemofs_opendir(FAR struct inode *mountpt, goto errout_with_pitr; } - mfs_pitr_init(sb, path, depth, pitr, false); + ret = mfs_pitr_init(sb, path, depth, pitr, false); + if (predict_false(ret < 0)) + { + finfo("Failed PITR initialization."); + goto errout_with_fsdirent; + } fsdirent->idx = 0; fsdirent->path = path; @@ -1199,9 +1212,15 @@ static int mnemofs_opendir(FAR struct inode *mountpt, finfo("Lock released."); return ret; +errout_with_fsdirent: + kmm_free(fsdirent); + errout_with_pitr: kmm_free(pitr); +errout_with_path: + mfs_free_patharr(path); + errout_with_lock: nxmutex_unlock(&MFS_LOCK(sb)); finfo("Lock released."); @@ -1271,8 +1290,8 @@ static int mnemofs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir, FAR struct dirent *entry) { - int ret = OK; - FAR struct mfs_sb_s *sb; + int ret = OK; + FAR struct mfs_sb_s *sb; FAR struct mfs_dirent_s *dirent; FAR struct mfs_fsdirent *fsdirent = (FAR struct mfs_fsdirent *) dir; @@ -1311,13 +1330,19 @@ static int mnemofs_readdir(FAR struct inode *mountpt, /* Regular direntries from here. */ - /* Here lies the `unlink` and `rmdir` bug, as sync can only update the - * current CTZ. + /* TODO: Need to think why *exactly* below line is needed. The LRU node + * seems to contain wrong size during opendir, but updating it here + * updates it to correct size, even though this updatedinfo is also + * called in opendir? */ - /* mfs_pitr_sync(sb, fsdirent->pitr, fsdirent->path, fsdirent->depth); */ + ret = mfs_lru_updatedinfo(sb, fsdirent->path, fsdirent->depth); + if (predict_false(ret < 0)) + { + goto errout_with_lock; + } - mfs_pitr_readdirent(sb, fsdirent->pitr, &dirent); + ret = mfs_pitr_readdirent(sb, fsdirent->path, fsdirent->pitr, &dirent); if (predict_false(ret < 0)) { goto errout_with_lock; @@ -1333,10 +1358,13 @@ static int mnemofs_readdir(FAR struct inode *mountpt, } memset(entry->d_name, 0, NAME_MAX + 1); - memcpy(entry->d_name, dirent->name, NAME_MAX); + memcpy(entry->d_name, dirent->name, dirent->namelen); entry->d_type = (S_ISDIR(dirent->mode) ? DTYPE_DIRECTORY: DTYPE_FILE); - mfs_pitr_adv(sb, fsdirent->pitr); + finfo("Size of direntry %u, current off %u.", MFS_DIRENTSZ(dirent), + fsdirent->pitr->c_off); + + mfs_pitr_adv_bydirent(fsdirent->pitr, dirent); mfs_free_dirent(dirent); errout_with_lock: @@ -1370,7 +1398,7 @@ static int mnemofs_readdir(FAR struct inode *mountpt, static int mnemofs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) { - int ret = OK; + int ret = OK; FAR struct mfs_sb_s *sb; struct mfs_fsdirent *fsdirent = (struct mfs_fsdirent *) dir; @@ -1503,6 +1531,8 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data, sb->log_pg_in_blk = log2(sb->pg_in_blk); sb->log_n_blks = log2(MFS_NBLKS(sb)); + list_initialize(&sb->of); + sb->rw_buf = kmm_zalloc(MFS_PGSZ(sb)); if (predict_false(sb->rw_buf == NULL)) { @@ -1762,11 +1792,10 @@ static int mnemofs_unlink(FAR struct inode *mountpt, FAR const char *relpath) static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, mode_t mode) { - int ret = OK; - int flags; - mfs_t depth; - FAR const char *child; - struct mfs_pitr_s pitr; + int ret = OK; + int flags; + mfs_t depth; + struct mfs_pitr_s pitr; FAR struct mfs_sb_s *sb; FAR struct mfs_path_s *path; @@ -1787,7 +1816,14 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, finfo("Lock acquired."); flags = mfs_get_patharr(sb, relpath, &path, &depth); - if ((flags & MFS_NEXIST) == 0) + if ((flags & MFS_EXIST) != 0) + { + finfo("File exists."); + + ret = -EEXIST; + goto errout_with_path; + } + else { if ((flags & MFS_P_EXIST) != 0) { @@ -1800,29 +1836,25 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, else { ret = -ENOTDIR; - goto errout_with_lock; + goto errout_with_path; } } else { ret = -ENOENT; - goto errout_with_lock; + goto errout_with_path; } } - else - { - ret = -EEXIST; - goto errout_with_lock; - } + memset(&path[depth - 1], 0, sizeof(struct mfs_path_s)); mfs_pitr_init(sb, path, depth, &pitr, true); - child = relpath; - finfo("Mode %x", mode); - ret = mfs_pitr_appendnew(sb, path, depth, &pitr, child, mode); + /* The last incomplete direntry will be added by mfs_pitr_appendnew. */ + + ret = mfs_pitr_appendnew(sb, path, depth, &pitr, relpath, mode); if (predict_false(ret < 0)) { - goto errout_with_pitr; + goto errout_with_path; } mfs_pitr_free(&pitr); @@ -1837,10 +1869,11 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, finfo("Mnemofs mkdir exited with ret %d.", ret); return ret; -errout_with_pitr: +errout_with_path: + mfs_free_patharr(path); + mfs_pitr_free(&pitr); -errout_with_lock: nxmutex_unlock(&MFS_LOCK(sb)); finfo("Lock released."); @@ -1869,10 +1902,10 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, static int mnemofs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) { - int ret = OK; - int flags; - mfs_t depth; - struct mfs_pitr_s pitr; + int ret = OK; + int flags; + mfs_t depth; + struct mfs_pitr_s pitr; FAR struct mfs_sb_s *sb; FAR struct mfs_path_s *path; @@ -1898,9 +1931,9 @@ static int mnemofs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) } mfs_pitr_init(sb, path, depth, &pitr, true); - mfs_pitr_adv_tochild(&pitr, path, depth); + mfs_pitr_adv_tochild(&pitr, path); - if (!mfs_obj_isempty(sb, &pitr)) + if (!mfs_obj_isempty(sb, path, &pitr)) { ret = -ENOTEMPTY; goto errout_with_pitr; @@ -1948,16 +1981,16 @@ static int mnemofs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, FAR const char *newrelpath) { - int ret = OK; - int oflags; - int nflags; - bool nexists; - bool odir = false; - bool ndir = false; - mfs_t odepth; - mfs_t ndepth; - struct mfs_pitr_s opitr; - struct mfs_pitr_s npitr; + int ret = OK; + int oflags; + int nflags; + bool nexists; + bool odir = false; + bool ndir = false; + mfs_t odepth; + mfs_t ndepth; + struct mfs_pitr_s opitr; + struct mfs_pitr_s npitr; FAR struct mfs_sb_s *sb; FAR struct mfs_path_s *opath; FAR struct mfs_path_s *npath; @@ -1978,7 +2011,7 @@ static int mnemofs_rename(FAR struct inode *mountpt, finfo("Lock acquired."); oflags = mfs_get_patharr(sb, oldrelpath, &opath, &odepth); - if ((oflags & MFS_NEXIST) != 0) + if ((oflags & MFS_EXIST) == 0) { ret = -ENOENT; goto errout_with_opath; @@ -1991,9 +2024,9 @@ static int mnemofs_rename(FAR struct inode *mountpt, goto errout_with_npath; } - odir = ((oflags & MFS_ISDIR) != 0); - ndir = ((nflags & MFS_ISDIR) != 0); - nexists = ((nflags & MFS_NEXIST) == 0); + odir = ((oflags & MFS_ISDIR) != 0); + ndir = ((nflags & MFS_ISDIR) != 0); + nexists = ((nflags & MFS_EXIST) != 0); if (nexists && odir && !ndir) { @@ -2016,11 +2049,11 @@ static int mnemofs_rename(FAR struct inode *mountpt, if (nexists) { - mfs_pitr_adv_tochild(&opitr, opath, odepth); - mfs_pitr_adv_tochild(&npitr, npath, ndepth); + mfs_pitr_adv_tochild(&opitr, opath); + mfs_pitr_adv_tochild(&npitr, npath); - mfs_pitr_readdirent(sb, &opitr, &odirent); - if (ndir && !mfs_obj_isempty(sb, &npitr)) + mfs_pitr_readdirent(sb, opath, &opitr, &odirent); + if (ndir && !mfs_obj_isempty(sb, npath, &npitr)) { ret = -ENOTEMPTY; goto errout_with_pitr; @@ -2031,7 +2064,7 @@ static int mnemofs_rename(FAR struct inode *mountpt, mfs_pitr_rm(sb, npath, ndepth); } - mfs_pitr_adv_tochild(&npitr, npath, ndepth); + mfs_pitr_adv_tochild(&npitr, npath); mfs_pitr_appenddirent(sb, npath, ndepth, &npitr, odirent); mfs_pitr_rmdirent(sb, opath, odepth, &opitr, odirent); @@ -2086,7 +2119,7 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath, FAR struct mfs_path_s *path; FAR struct mfs_dirent_s *dirent = NULL; - finfo("Mnemofs stat for path %s.", relpath); + finfo("Mnemofs stat for path \"%s\".", relpath); DEBUGASSERT(mountpt != NULL); sb = mountpt->i_private; @@ -2101,26 +2134,33 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath, finfo("Lock acquired."); ret_flags = mfs_get_patharr(sb, relpath, &path, &depth); - if (ret_flags & MFS_NEXIST) + if ((ret_flags & MFS_EXIST) == 0) { ret = -ENOENT; - goto errout_with_lock; + goto errout_with_path; } - finfo("Got path array. Depth %u for path \"%s\"", depth, relpath); + finfo("Got path array. Depth %u for path \"%s\". Return flags %u.", depth, + relpath, ret_flags); + + ret = mfs_lru_updatedinfo(sb, path, depth); + if (predict_false(ret < 0)) + { + goto errout_with_path; + } mfs_pitr_init(sb, path, depth, &pitr, true); - mfs_pitr_adv_tochild(&pitr, path, depth); + mfs_pitr_adv_tochild(&pitr, path); - ret = mfs_pitr_readdirent(sb, &pitr, &dirent); + ret = mfs_pitr_readdirent(sb, path, &pitr, &dirent); if (predict_false(ret < 0)) { - goto errout_with_lock; + goto errout_with_path; } else if (dirent == NULL) { ret = -ENOENT; - goto errout_with_lock; + goto errout_with_path; } finfo("Read stats."); @@ -2136,13 +2176,14 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath, mfs_free_dirent(dirent); mfs_pitr_free(&pitr); + +errout_with_path: mfs_free_patharr(path); -errout_with_lock: finfo("Lock released."); nxmutex_unlock(&MFS_LOCK(sb)); errout: - finfo("ret %d", ret); + finfo("Ret %d", ret); return ret; } diff --git a/fs/mnemofs/mnemofs.h b/fs/mnemofs/mnemofs.h index df1d1040b3c56..ab6c2476eb977 100644 --- a/fs/mnemofs/mnemofs.h +++ b/fs/mnemofs/mnemofs.h @@ -88,9 +88,12 @@ #define MFS_NBLKS(sb) ((sb)->n_blks) #define MFS_NPGS(sb) (MFS_NBLKS(sb) * MFS_PGINBLK(sb)) +#define MFS_HASHSZ 16 #define MFS_CTZ_SZ(l) ((l)->sz) -#define MFS_DIRENTSZ(dirent) (sizeof(struct mfs_dirent_s) \ - + (dirent)->namelen) +#define MFS_DIRENTSZ(dirent) ((mfs_t) (sizeof(struct mfs_dirent_s) \ + + (dirent)->namelen)) + +#define MFS_JRNL_LIM(sb) (MFS_JRNL(sb).n_blks) /* TODO: 50-75% */ /**************************************************************************** * Public Types @@ -112,7 +115,7 @@ enum MFS_PATH_FLAGS { MFS_ISDIR = (1 << 0), /* Path is a directory. */ MFS_ISFILE = (1 << 1), /* Path is a file. */ - MFS_NEXIST = (1 << 2), /* Path No Exist */ + MFS_EXIST = (1 << 2), /* Path Exists */ MFS_FINPATH = (1 << 3), /* File in midele of path before bottom most * child. Not reachable. */ @@ -227,7 +230,10 @@ struct mfs_node_s mfs_t sz; mfs_t range_min; mfs_t range_max; - FAR struct mfs_path_s path[]; + struct timespec st_mtim; + struct timespec st_atim; + struct timespec st_ctim; + FAR struct mfs_path_s *path; }; /* Common Part Open File Descriptor */ @@ -253,9 +259,9 @@ struct mfs_ofd_s struct mfs_dirent_s { - uint8_t name_hash; /* Should be at start to improve efficiency. */ - mfs_t sz; + uint16_t name_hash; /* Should be at start to improve efficiency. */ uint16_t mode; + mfs_t sz; struct timespec st_atim; /* Time of last access */ struct timespec st_mtim; /* Time of last modification */ struct timespec st_ctim; /* Time of last status change */ @@ -271,9 +277,12 @@ struct mfs_pitr_s struct mfs_path_s p; /* Parent representation */ mfs_t depth; mfs_t c_off; /* Current offset. */ - mfs_t sz; /* Parent's size. */ }; +/* TODO: depth >= 1 */ + +/* IMP TODO: sizeof(x) != size of buffer required to store it. Need to fix. */ + /**************************************************************************** * Public Data ****************************************************************************/ @@ -411,131 +420,157 @@ static inline mfs_t mfs_popcnt(mfs_t x) /* mnemofs_journal.c */ /**************************************************************************** - * Name: mfs_jrnl_newlog + * Name: mfs_jrnl_init * * Description: - * Add a new log to the journal. + * Initialize journal if device is already formatted. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Length of path. - * new_ctz - The updated location. + * sb - Superblock instance of the device. + * blk - First block of the journal. * * Returned Value: * 0 - OK * < 0 - Error * - * Assumptions/Limitations: - * Assumes the CTZ list to be updated is `path[depth - 1].ctz`. - * ****************************************************************************/ -int mfs_jrnl_newlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz); +int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk); /**************************************************************************** - * Name: mfs_jrnl_updatepath + * Name: mfs_jrnl_fmt * * Description: - * Updates the path of a CTZ list by applies all changes from the journal. + * Format a journal to the device. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Length of path. + * sb - Superblock instance of the device. + * blk1 - First master block for the journal. + * blk2 - Second master block for the journal. * * Returned Value: * 0 - OK * < 0 - Error * * Assumptions/Limitations: - * Assumes the CTZ list to be updated is `path[depth - 1].ctz`. + * If blk1 == 0 and blk2 == 0, this means that this will also format in the + * master blocks. If this is not satisfied, the provided values will be + * taken to denote the master nodes. * ****************************************************************************/ -int mfs_jrnl_updatepath(FAR const struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth); +int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2); /**************************************************************************** - * Name: mfs_jrnl_init + * Name: mfs_jrnl_free * * Description: - * Initialize journal if device is already formatted. + * Free the journal. * * Input Parameters: - * sb - Superblock instance of the device. - * blk - First block of the journal. + * sb - Superblock instance of the device. + * + ****************************************************************************/ + +void mfs_jrnl_free(FAR struct mfs_sb_s * const sb); + +/**************************************************************************** + * Name: mfs_jrnl_blkidx2blk + * + * Description: + * Gets the block number of a journal block at an index. + * + * Input Parameters: + * sb - Superblock instance of the device. + * blk_idx - Index of the block who's block number to find. * * Returned Value: - * 0 - OK - * < 0 - Error + * Block number. + * + * Assumptions/Limitations: + * Assumes valid index. This index can also include master blocks. Also + * assumes, for now, that the entire journal array can fit in the first + * block. * ****************************************************************************/ -int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk); +mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, + const mfs_t blk_idx); /**************************************************************************** - * Name: mfs_jrnl_fmt + * Name: mfs_jrnl_updatedinfo * * Description: - * Format a journal to the device. + * Update the path information from the journal. * * Input Parameters: - * sb - Superblock instance of the device. - * blk1 - First master block for the journal. - * blk2 - Second master block for the journal. + * sb - Superblock instance of the device. + * path - "Base state" path. + * depth - Path depth. * * Returned Value: * 0 - OK * < 0 - Error * * Assumptions/Limitations: - * If blk1 == 0 and blk2 == 0, this means that this will also format in the - * master blocks. If this is not satisfied, the provided values will be - * taken to denote the master nodes. + * This applies updates over data that is already gathered from the data + * section of the flash. The data section is the "base state" over which + * the updates in the journal are applied. * ****************************************************************************/ -int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2); +int mfs_jrnl_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth); /**************************************************************************** - * Name: mfs_jrnl_blkidx2blk + * Name: mfs_jrnl_wrlog * * Description: - * Gets the block number of a journal block at an index. + * Write a log for LRU node when its popped from the LRU. * * Input Parameters: * sb - Superblock instance of the device. - * blk_idx - Index of the block who's block number to find. + * node - LRU node. + * loc_new - New location of the CTZ skip list. + * sz_new - New size of the CTZ skip list. * * Returned Value: - * Block number. + * 0 - OK + * < 0 - Error * * Assumptions/Limitations: - * Assumes valid index. This index can also include master blocks. Also - * assumes, for now, that the entire journal array can fit in the first - * block. + * When a node from LRU is flushed, it's written to the data in any space + * that is available according to the block allocator, and the new location + * is recorded as a log along with the old location. Any log of this same + * CTZ skip list in the journal will use this "snapshot" of the location, + * ie. the updated path will be used until another log of the same CTZ + * skip list is stored, after which the path will be updated again, and + * so on. * ****************************************************************************/ -mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, - const mfs_t blk_idx); +int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb, + const struct mfs_node_s node, + const struct mfs_ctz_s loc_new, const mfs_t sz_new); /**************************************************************************** - * Name: mfs_jrnl_free + * Name: mfs_jrnl_flush * * Description: - * Free the journal. + * Flush the entire journal. This is the entry point of the entire flush + * operation and includes messing with the master node as well. * * Input Parameters: * sb - Superblock instance of the device. * + * Returned Value: + * 0 - OK + * < 0 - Error + * ****************************************************************************/ -void mfs_jrnl_free(FAR struct mfs_sb_s * const sb); +int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb); /* mnemofs_blkalloc.c */ @@ -639,12 +674,16 @@ void mfs_ba_blkmarkdel(FAR struct mfs_sb_s * const sb, mfs_t blk); * Input Parameters: * sb - Superblock instance of the device. * + * Returned Value: + * 0 - OK + * < 0 - Error + * * Assumptions/Limitations: * This assumes a locked environment when called. * ****************************************************************************/ -void mfs_ba_delmarked(FAR struct mfs_sb_s * const sb); +int mfs_ba_delmarked(FAR struct mfs_sb_s * const sb); /**************************************************************************** * Name: mfs_ba_markusedpg @@ -847,6 +886,10 @@ int mfs_erase_nblks(FAR const struct mfs_sb_s * const sb, const off_t blk, uint8_t mfs_arrhash(FAR const char *arr, ssize_t len); +/* TODO: Put below in place of above. */ + +uint16_t mfs_hash(FAR const char *arr, ssize_t len); + /**************************************************************************** * Name: mfs_ser_8 * @@ -990,6 +1033,12 @@ FAR char *mfs_ser_ctz(FAR const struct mfs_ctz_s * const x, FAR const char *mfs_deser_ctz(FAR const char * const in, FAR struct mfs_ctz_s * const x); +FAR char *mfs_ser_path(FAR const struct mfs_path_s * const x, + FAR char * const out); + +FAR const char *mfs_deser_path(FAR const char * const in, + FAR struct mfs_path_s * const x); + /**************************************************************************** * Name: mfs_ser_timespec * @@ -1080,7 +1129,7 @@ mfs_t mfs_v2n(mfs_t n); * Name: mfs_set_msb * * Description: - * Set the least significant of the most significant unset bits. + * The mosr significant set bit location. * * Input Parameters: * n - Number. @@ -1092,104 +1141,76 @@ mfs_t mfs_v2n(mfs_t n); mfs_t mfs_set_msb(mfs_t n); +bool mfs_ctz_eq(FAR const struct mfs_ctz_s * const a, + FAR const struct mfs_ctz_s * const b); + +bool mfs_path_eq(FAR const struct mfs_path_s * const a, + FAR const struct mfs_path_s * const b); + /* mnemofs_ctz.c */ /**************************************************************************** - * Name: mfs_ctz_rdfromoff + * Name: mfs_ctz_rdfromoff_new * * Description: - * Read data from data offset in a CTZ list. This includes updates from the - * journal. The ctz list is taken as the last element in the path, got - * using `path[depth - 1]`. + * Read from a specific offset into the data in a CTZ file. New version. * * Input Parameters: * sb - Superblock instance of the device. - * data_off - Data offset into the CTZ list. - * path - CTZ representation of the relpath. - * depth - Depth of the path. - * buf - Buffer will be populated with the contents. - * buflen - Length of `buf`. - * - * Returned Value: - * 0 - OK - * < 0 - Error + * ctz - CTZ list. + * data_off - Offset into the data. + * len - Length of the buffer. + * buf - Buffer to store read contents. * * Assumptions/Limitations: - * This updates the value of path to reflect the latest location. + * The CTZ list provided should be the updated location from the journal. * ****************************************************************************/ -int mfs_ctz_rdfromoff(FAR struct mfs_sb_s * const sb, mfs_t data_off, - FAR struct mfs_path_s * const path, const mfs_t depth, - FAR char *buf, mfs_t buflen); +int mfs_ctz_rdfromoff(FAR const struct mfs_sb_s * const sb, + const struct mfs_ctz_s ctz, mfs_t data_off, + mfs_t len, FAR char * buf); /**************************************************************************** - * Name: mfs_ctz_wrtooff + * Name: mfs_ctz_wrtnode_new * * Description: - * Replace `o_bytes` of data from CTZ list with `n_bytes` of data from - * `buf` at CTZ data offset `data_off`. - * - * In mnemofs, the CTZ lists are all stored in a Copy On Write manner. - * Hence to update a CTZ list, the common CTZ blocks will be kept as it is, - * then in the CTZ block containing `data_off`, the bytes appearing before - * `data_off` (which remain unchanged) will be copied to the new CTZ block - * then `n_bytes` of content from `buf` will follow, and then the data from - * `data_off + o_bytes` will follow (both these will be copied to new - * CTZ blocks as well due to Copy On Write). - * - * The new location will be written to the journal upon success as well. + * Write an LRU node to the flash. It also adds a log of it to the journal. * * Input Parameters: - * sb - Superblock instance of the device. - * data_off - Data offset into the CTZ list. - * o_bytes - Number of bytes in old CTZ list from `data_off` that will be - * replaced. - * n_bytes - Number of bytes in new CTZ list from `data_off` that will be - * replacing `o_bytes`. - * o_ctz_sz - The size in bytes of the old CTZ list. - * path - CTZ representation of the relpath. - * depth - Depth of the path. - * buf - Buffer that contains the data to be replaced in CTZ list. - * ctz - CTZ list to be updated with the new position. - * - * Returned Value: - * 0 - OK - * < 0 - Error + * sb - Superblock instance of the device. + * node - LRU node * * Assumptions/Limitations: - * This updates the value of path to reflect the latest location.s + * - Assumes path is updated by journal. This will also write corresponding + * journal log. + * + * - This is the most computationally heavy part of the entire file system + * from a human POV, and one of the most for MCU or computer (as init + * methods are heavier). * ****************************************************************************/ -int mfs_ctz_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t o_bytes, const mfs_t n_bytes, - mfs_t o_ctz_sz, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf, - FAR struct mfs_ctz_s *ctz); +int mfs_ctz_wrtnode(FAR struct mfs_sb_s * const sb, + const struct mfs_node_s * const node); + +/* mnemofs_lru.c */ /**************************************************************************** - * Name: mfs_ctz_nwrtooff + * Name: mfs_lru_ctzflush * * Description: - * Write deltas of an LRU node to flash. + * Flush the updates of a CTZ list inside the LRU to the flash. * * Input Parameters: - * sb - Superblock instance of the device. - * node - LRU Node. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * ctz_sz - Number of bytes in the data of the CTZ list. - * new_ctz - New CTZ location + * sb - Superblock instance of the device. + * path - CTZ representation of the relpath. + * depth - Depth of path. * ****************************************************************************/ -int mfs_ctz_nwrtooff(FAR struct mfs_sb_s * const sb, - FAR struct mfs_node_s *node, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz, FAR struct mfs_ctz_s *new_ctz); - -/* mnemofs_lru.c */ +int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, const mfs_t depth); /**************************************************************************** * Name: mfs_lru_del @@ -1201,15 +1222,14 @@ int mfs_ctz_nwrtooff(FAR struct mfs_sb_s * const sb, * sb - Superblock instance of the device. * off - Offset into the data. * bytes - Number of bytes to delete. - * ctz_sz - Number of bytes in the data of the CTZ list. * path - CTZ representation of the relpath. * depth - Depth of path. * ****************************************************************************/ -int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t off, - mfs_t bytes, mfs_t ctz_sz, - FAR struct mfs_path_s * const path, const mfs_t depth); +int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t data_off, + mfs_t bytes, FAR struct mfs_path_s * const path, + const mfs_t depth); /**************************************************************************** * Name: mfs_lru_wr @@ -1221,7 +1241,6 @@ int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t off, * sb - Superblock instance of the device. * data_off - Offset into the data. * bytes - Number of bytes to delete. - * ctz_sz - Number of bytes in the data of the CTZ list. * path - CTZ representation of the relpath. * depth - Depth of path. * buf - Buffer. @@ -1229,26 +1248,21 @@ int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t off, ****************************************************************************/ int mfs_lru_wr(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t bytes, mfs_t ctz_sz, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf); + mfs_t bytes, FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char *buf); /**************************************************************************** - * Name: mfs_lru_ctzflush + * Name: mfs_lru_init * * Description: - * Flush the updates of a CTZ list inside the LRU to the flash. + * Initialize LRU. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * ctz_sz - Size of the CTZ file. + * sb - Superblock instance of the device. * ****************************************************************************/ -int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz); +void mfs_lru_init(FAR struct mfs_sb_s * const sb); /**************************************************************************** * Name: mfs_lru_rdfromoff @@ -1266,40 +1280,52 @@ int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -int mfs_lru_rdfromoff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, +int mfs_lru_rdfromoff(FAR const struct mfs_sb_s * const sb, + const mfs_t data_off, FAR struct mfs_path_s * const path, const mfs_t depth, FAR char *buf, const mfs_t buflen); /**************************************************************************** - * Name: mfs_lru_init + * Name: mfs_lru_updatedinfo * * Description: - * Initialize LRU. + * Update information of the path. * * Input Parameters: - * sb - Superblock instance of the device. + * sb - Superblock instance of the device. + * path - CTZ representation of the relpath. + * depth - Depth of path. + * + * Assumptions/Limitations: + * The will update path. * ****************************************************************************/ -void mfs_lru_init(FAR struct mfs_sb_s * const sb); +int mfs_lru_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth); /**************************************************************************** - * Name: mfs_lru_updatedsz + * Name: mfs_lru_updatectz * * Description: - * Update size of a CTZ list. + * Update CTZ location of an fs object. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * n_sz - New size. + * sb - Superblock instance of the device. + * path - Old CTZ representation of the relpath. + * depth - Depth of path. + * new_ctz - New CTZ location. + * + * Assumptions/Limitations: + * The update the CTZ portion of the direntry in the parent. + * This updates the path as well. * ****************************************************************************/ -void mfs_lru_updatedsz(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, mfs_t *n_sz); +int mfs_lru_updatectz(FAR struct mfs_sb_s * sb, + FAR struct mfs_path_s * const path, const mfs_t depth, + const struct mfs_ctz_s new_ctz); /* mnemofs_master.c */ @@ -1436,8 +1462,8 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -int mfs_get_patharr(FAR struct mfs_sb_s *const sb, - FAR const char *relpath, FAR struct mfs_path_s **path, +int mfs_get_patharr(FAR const struct mfs_sb_s * const sb, + FAR const char * relpath, FAR struct mfs_path_s **path, FAR mfs_t *depth); /**************************************************************************** @@ -1472,7 +1498,8 @@ void mfs_free_patharr(FAR struct mfs_path_s *path); ****************************************************************************/ bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr); + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr); /**************************************************************************** * Name: mfs_pitr_init @@ -1509,9 +1536,9 @@ bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -void mfs_pitr_init(FAR struct mfs_sb_s * const sb, +int mfs_pitr_init(FAR const struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, - const mfs_t depth, FAR struct mfs_pitr_s *pitr, + const mfs_t depth, FAR struct mfs_pitr_s * const pitr, bool child); /**************************************************************************** @@ -1529,7 +1556,7 @@ void mfs_pitr_init(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr); +void mfs_pitr_free(FAR const struct mfs_pitr_s * const pitr); /**************************************************************************** * Name: mfs_pitr_adv @@ -1547,11 +1574,12 @@ void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr); * ****************************************************************************/ -void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr); +int mfs_pitr_adv(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr); /**************************************************************************** - * Name: mfs_pitr_adv_dirent + * Name: mfs_pitr_adv_bydirent * * Description: * Advance a pitr to the next direntry by using current direntry. @@ -1567,8 +1595,8 @@ void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -void mfs_pitr_adv_dirent(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent); +void mfs_pitr_adv_bydirent(FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_dirent_s * const dirent); /**************************************************************************** * Name: mfs_pitr_adv_off @@ -1598,7 +1626,6 @@ void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, * Input Parameters: * pitr - Parent iterator. * path - CTZ representation of the relpath - * depth - Depth of path. * * Assumptions/Limitations: * This assumes that the pitr is initialized for the immediate parent of the @@ -1607,8 +1634,7 @@ void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, ****************************************************************************/ void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth); + FAR const struct mfs_path_s * const path); /**************************************************************************** * Name: mfs_pitr_reset @@ -1623,30 +1649,6 @@ void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr); -/**************************************************************************** - * Name: mfs_pitr_sync - * - * Description: - * Sync a pitr. - * - * In mnemofs, when moving between locked contexts, it may happen that a - * a CTZ is moved to some place is between. This updates the location by - * reading the journal to check for any related logs in the journal. - * Updates contained in the LRU do not update the location of a CTZ list. - * - * Input Parameters: - * sb - Superblock instance of the device. - * pitr - Parent iterator. - * path - CTZ representation of the relpath - * depth - Depth of path. - * - ****************************************************************************/ - -void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth); - /**************************************************************************** * Name: mfs_pitr_readdirent * @@ -1667,7 +1669,8 @@ void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, +int mfs_pitr_readdirent(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, FAR struct mfs_pitr_s * const pitr, FAR struct mfs_dirent_s **dirent); @@ -1734,7 +1737,7 @@ bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, + FAR struct mfs_pitr_s * const pitr, FAR const struct mfs_dirent_s * const dirent); /**************************************************************************** @@ -1745,24 +1748,27 @@ int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, * initialized in pitr. This creates the direntry. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * pitr - Parent Iterator. - * dirent - Directory entry to be added. - * mode - Mode of the file/directory. + * sb - Superblock instance of the device. + * path - CTZ representation of the relpath. + * depth - Depth of path. + * pitr - Parent Iterator. + * relpath - Relative path of the fs object. + * mode - Mode of the file/directory. * * Returned Value: * 0 - OK * < 0 - Error * + * Assumptions/Limitations: + * This assumes that the fs object desired to be appended appears at the + * end of the entire relpath. + * ****************************************************************************/ int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, - FAR const char * const child_name, const mode_t mode); + FAR struct mfs_path_s * const path, const mfs_t depth, + FAR struct mfs_pitr_s * const pitr, + FAR const char * const relpath, const mode_t mode); /**************************************************************************** * Name: mfs_pitr_rmdirent diff --git a/fs/mnemofs/mnemofs_blkalloc.c b/fs/mnemofs/mnemofs_blkalloc.c index 254675995f4c5..9bc135c6d1ca1 100644 --- a/fs/mnemofs/mnemofs_blkalloc.c +++ b/fs/mnemofs/mnemofs_blkalloc.c @@ -91,7 +91,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define BMAP_GET(bmap, idx, off) ((bmap)[(idx)] & (1 << (off))) +#define BMAP_GET(bmap, idx, off) (((bmap)[(idx)] & (1 << (off))) != 0) #define BMAP_SET(bmap, idx, off) ((bmap)[(idx)] |= (1 << (off))) #define DEL_ARR_BLK(sb, blk) (MFS_BA((sb)).k_del[(blk) * sizeof(size_t)]) #define DEL_ARR_PG(sb, pg) (DEL_ARR_BLK(sb, MFS_PG2BLK((sb), (pg)))) @@ -134,14 +134,8 @@ static int is_blk_writeable(FAR struct mfs_sb_s * const sb, * idx - Populated later with the index of page in MFS_BA(sb).bmap_upgs * off - Populated later with the offset of page in MFS_BA(sb).bmap_upgs * - * Returned Value: - * MFS_BLK_BAD - If the block of the page is a bad block. - * MFS_PG_USED - If the page is being used. - * MFS_BLK_ERASABLE - If page can be allocated, but block needs erase. - * MFS_PG_FREE - If the page is free. - * * Assumptions/Limitations: - * Does not check validity of the page number. + * Does not check validity of the index. * ****************************************************************************/ @@ -503,13 +497,28 @@ void mfs_ba_pgmarkdel(FAR struct mfs_sb_s * const sb, mfs_t pg) void mfs_ba_blkmarkdel(FAR struct mfs_sb_s * const sb, mfs_t blk) { - mfs_erase_blk(sb, blk); - DEL_ARR_BLK(sb, blk) = 0; + DEL_ARR_BLK(sb, blk) = MFS_PGINBLK(sb); } -void mfs_ba_delmarked(FAR struct mfs_sb_s * const sb) +int mfs_ba_delmarked(FAR struct mfs_sb_s * const sb) { - /* TODO */ + int ret = OK; + mfs_t i; + + for (i = 1; i < MFS_NBLKS(sb); i++) + { + if (DEL_ARR_BLK(sb, i) == MFS_PGINBLK(sb)) + { + ret = mfs_erase_blk(sb, i); + + if (ret != OK) + { + return ret; + } + } + } + + return ret; } /* Mark a page as being used. Used by master node during initial format and @@ -517,15 +526,16 @@ void mfs_ba_delmarked(FAR struct mfs_sb_s * const sb) void mfs_ba_markusedpg(FAR struct mfs_sb_s * const sb, mfs_t pg) { - mfs_t idx; + mfs_t idx; uint8_t off; + pg2bmap(pg, &idx, &off); BMAP_SET(MFS_BA(sb).bmap_upgs, idx, off); /* Set as used */ } void mfs_ba_markusedblk(FAR struct mfs_sb_s * const sb, mfs_t blk) { - mfs_t i = 0; + mfs_t i = 0; mfs_t pg = MFS_BLK2PG(sb, blk); for (i = 0; i < MFS_PGINBLK(sb); i++) diff --git a/fs/mnemofs/mnemofs_ctz.c b/fs/mnemofs/mnemofs_ctz.c index f24111f34eb8b..9db41c664397d 100644 --- a/fs/mnemofs/mnemofs_ctz.c +++ b/fs/mnemofs/mnemofs_ctz.c @@ -157,7 +157,11 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, static mfs_t ctz_idx_nptrs(const mfs_t idx) { - return idx == 0 ? 0 : mfs_ctz(idx) + 1; + mfs_t ret; + + ret = (idx == 0) ? 0 : mfs_ctz(idx) + 1; + finfo("Number of pointers for %u index is %u.", idx, ret); + return ret; } /**************************************************************************** @@ -179,17 +183,29 @@ static mfs_t ctz_idx_nptrs(const mfs_t idx) static void ctz_off2loc(FAR const struct mfs_sb_s * const sb, mfs_t off, FAR mfs_t *idx, FAR mfs_t *pgoff) { - const mfs_t den = MFS_PGSZ(sb) - 8; - if (off < MFS_PGSZ(sb)) + const mfs_t wb = sizeof(mfs_t); + const mfs_t den = MFS_PGSZ(sb) - 2 * wb; + + if (off < den) { *idx = 0; *pgoff = off; return; } - *idx = floor((off - 4 * (__builtin_popcount((off / den) - 1) + 2)) - / den); - *pgoff = off - den * (*idx) - 4 * __builtin_popcount(*idx); + if (idx != NULL) + { + *idx = (off - wb * (__builtin_popcount((off / den) - 1) + 2)) / den; + } + + if (pgoff != NULL) + { + *pgoff = off - den * (*idx) - wb * __builtin_popcount(*idx) + - (ctz_idx_nptrs(*idx) * wb); + } + + finfo("Offset %u. Calculated index %u and page offset %u.", off, *idx, + *pgoff); } /**************************************************************************** @@ -210,7 +226,11 @@ static void ctz_off2loc(FAR const struct mfs_sb_s * const sb, mfs_t off, static mfs_t ctz_blkdatasz(FAR const struct mfs_sb_s * const sb, const mfs_t idx) { - return MFS_PGSZ(sb) - (ctz_idx_nptrs(idx) * MFS_LOGPGSZ(sb)); + mfs_t ret; + + ret = MFS_PGSZ(sb) - (ctz_idx_nptrs(idx) * MFS_LOGPGSZ(sb)); + finfo("Block data size for index %u is %u.", idx, ret); + return ret; } /**************************************************************************** @@ -261,6 +281,11 @@ static mfs_t ctz_travel(FAR const struct mfs_sb_s * const sb, mfs_t idx_src, mfs_read_page(sb, buf, 4, pg, MFS_PGSZ(sb) - (4 * pow)); mfs_deser_mfs(buf, &pg); idx -= (1 << pow); + + if (pg == 0) + { + return 0; + } } if (idx == idx_dest) @@ -278,8 +303,16 @@ static mfs_t ctz_travel(FAR const struct mfs_sb_s * const sb, mfs_t idx_src, mfs_deser_mfs(buf, &pg); idx -= (1 << pow); diff -= (1 << pow); + + if (pg == 0) + { + return 0; + } } + finfo("Travel from index %u at page %u to index %u at page %u.", idx_src, + pg_src, idx_dest, pg); + return pg; } @@ -299,11 +332,11 @@ static mfs_t ctz_travel(FAR const struct mfs_sb_s * const sb, mfs_t idx_src, * buffer, then write the data to the flash. * * Input Parameters: - * sb - Superblock instance of the device. - * ctz - CTZ list to use as a reference. - * idx - Index of the block who's supposed pointers are to be copied. - * buf - Buffer representing the entire CTZ block where pointers are - * copied to. + * sb - Superblock instance of the device. + * ctz - CTZ list to use as a reference. + * idx - Index of the block who's supposed pointers are to be copied. + * buf - Buffer representing the entire CTZ block where pointers are + * copied to. * * Assumptions/Limitations: * This assumes `idx` is not more than `ctz->idx_e + 1`. @@ -330,12 +363,19 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, if (idx != ctz.idx_e + 1) { + /* We travel to the second last "known" CTZ block. */ + ctz.pg_e = ctz_travel(sb, ctz.idx_e, ctz.pg_e, idx - 1); ctz.idx_e = idx - 1; } buf += MFS_PGSZ(sb); /* Go to buf + pg_sz */ + DEBUGASSERT(idx == ctz.idx_e + 1); + + finfo("Copying %u pointers for CTZ (%u, %u) at index %u.", n_ptrs, + ctz.idx_e, ctz.pg_e, idx); + for (i = 0; i < n_ptrs; i++) { if (predict_false(i == 0)) @@ -355,6 +395,8 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, buf -= MFS_CTZ_PTRSZ; mfs_ser_mfs(prev_pg, buf); + + finfo("Copied %u page number to %uth pointer.", prev_pg, i); } } @@ -362,409 +404,257 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, * Public Functions ****************************************************************************/ -int mfs_ctz_rdfromoff(FAR struct mfs_sb_s * const sb, mfs_t data_off, - FAR struct mfs_path_s * const path, const mfs_t depth, - FAR char *buf, mfs_t buflen) +int mfs_ctz_rdfromoff(FAR const struct mfs_sb_s * const sb, + const struct mfs_ctz_s ctz, mfs_t data_off, + mfs_t len, FAR char * buf) { - int ret = OK; - mfs_t sz; - mfs_t pg; - mfs_t idx; - mfs_t off; - struct mfs_ctz_s ctz; - - /* Get updated location from the journal */ - - finfo("Journal upd!"); - DEBUGASSERT(depth > 0); - mfs_jrnl_updatepath(sb, path, depth); - ctz = path[depth - 1].ctz; - - ctz_off2loc(sb, data_off, &idx, &off); - - /* TODO: Make the traversal in reverse direction. It would cause - * a lot less traversals. - */ - - while (idx <= ctz.idx_e && off - data_off < buflen) - { - sz = ctz_blkdatasz(sb, idx); - pg = ctz_travel(sb, ctz.idx_e, ctz.pg_e, idx); - - ret = mfs_read_page(sb, buf, sz, pg, off); - if (predict_false(ret < 0)) - { - return ret; - } - - off = 0; - idx++; - buf += sz; - } - - return ret; -} - -int mfs_ctz_nwrtooff(FAR struct mfs_sb_s * const sb, - FAR struct mfs_node_s *node, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz, FAR struct mfs_ctz_s *new_ctz) -{ - int ret = OK; - bool del; - mfs_t pg; - mfs_t sz; - mfs_t inc; - mfs_t idx; - mfs_t bytes; - mfs_t pgoff; - mfs_t itr_min; - mfs_t itr_max; - mfs_t neg_off; /* Negative offset due to delete. */ - FAR char *buf = NULL; - const mfs_t range_min = node->range_min; - const mfs_t range_max = node->range_max; - struct mfs_ctz_s ctz; - FAR struct mfs_delta_s *delta = NULL; - - buf = kmm_zalloc(MFS_PGSZ(sb)); - if (predict_false(buf == NULL)) + int ret = OK; + mfs_t i; + mfs_t rd_sz; + mfs_t cur_pg; + mfs_t cur_idx; + mfs_t cur_pgoff; + mfs_t end_idx; + mfs_t end_pgoff; + mfs_t pg_rd_sz; + + ctz_off2loc(sb, data_off + len, &cur_idx, &cur_pgoff); + ctz_off2loc(sb, data_off, &end_idx, &end_pgoff); + + if (ctz.idx_e < cur_idx || ctz.idx_e < end_idx) { - ret = -ENOMEM; goto errout; } - /* CoW of items in block before range_min */ + cur_pg = ctz_travel(sb, ctz.idx_e, ctz.pg_e, cur_idx); + rd_sz = 0; - ctz_off2loc(sb, range_min, &idx, &pgoff); - DEBUGASSERT(depth > 0); - pg = ctz_travel(sb, path[depth - 1].ctz.idx_e, path[depth - 1].ctz.pg_e, - idx); - if (predict_false(pg == 0)) + if (predict_false(cur_pg == 0)) { - ret = -EINVAL; - goto errout_with_buf; + goto errout; } - ctz.idx_e = idx - 1; - ctz.pg_e = pg; - mfs_read_page(sb, buf, pgoff, pg, pgoff); - - /* Updates */ - - bytes = range_min; - itr_max = range_min; - neg_off = 0; - del = false; + /* O(n) read by reading in reverse. */ - while (bytes < range_max) + if (cur_idx != end_idx) { - if (!del) - { - memset(buf, 0, MFS_PGSZ(sb)); - sz = ctz_blkdatasz(sb, ctz.idx_e + 1); - itr_min = itr_max; - itr_max += sz; - ctz_copyidxptrs(sb, ctz, ctz.idx_e + 1, buf); - } - else + for (i = cur_idx; i >= end_idx; i--) { - inc = itr_max - itr_min; - itr_min = itr_max; - itr_min = sz - inc; - } - - del = false; - mfs_ctz_rdfromoff(sb, itr_min + neg_off, path, depth, buf + pgoff, sz); - - list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) - { - if (delta->off + delta->n_b <= itr_min || itr_max <= delta->off) + if (predict_false(i == cur_idx)) { - /* Out of range */ - - continue; + pg_rd_sz = cur_pgoff; + ret = mfs_read_page(sb, buf - pg_rd_sz, pg_rd_sz, cur_pg, + 0); + cur_pgoff = 0; } - - inc = MIN(itr_max, delta->off + delta->n_b) - delta->off; - - if (delta->upd != NULL) + else if (predict_false(i == end_idx)) { - /* Update */ - - memcpy(buf + pgoff + (delta->off - itr_min), delta->upd, inc); + pg_rd_sz = ctz_blkdatasz(sb, i) - end_pgoff; + ret = mfs_read_page(sb, buf - pg_rd_sz, pg_rd_sz, cur_pg, + end_pgoff); } else { - /* Delete */ - - memmove(buf + pgoff + (delta->off - itr_min), - buf + pgoff + (delta->off - itr_min) + inc, - itr_max - (delta->off + inc)); - itr_max -= inc; - neg_off += inc; - del = true; + pg_rd_sz = ctz_blkdatasz(sb, i); + ret = mfs_read_page(sb, buf - pg_rd_sz, pg_rd_sz, cur_pg, + 0); } - } - bytes += itr_max - itr_min; - - if (!del) - { - pgoff = 0; - pg = mfs_ba_getpg(sb); - if (pg == 0) + if (predict_false(ret == 0)) { - ret = -ENOSPC; - goto errout_with_buf; + ret = -EINVAL; + goto errout; } - mfs_write_page(sb, buf, MFS_PGSZ(sb), pg, 0); - ctz.pg_e = pg; - ctz.idx_e++; + buf -= pg_rd_sz; } - else - { - pgoff += itr_max - itr_min; - } - } - /* Copy rest of the file. */ + cur_pg = ctz_travel(sb, cur_idx, cur_pg, cur_idx - 1); - if (del) - { - mfs_ctz_rdfromoff(sb, itr_max + neg_off, path, depth, buf + pgoff, - sz - pgoff); - pg = mfs_ba_getpg(sb); - if (pg == 0) + if (predict_false(cur_pg == 0)) { - ret = -ENOSPC; - goto errout_with_buf; + ret = -EINVAL; + goto errout; } - - mfs_write_page(sb, buf, MFS_PGSZ(sb), pg, 0); - ctz.pg_e = pg; - ctz.idx_e++; - itr_max += sz - pgoff; - pgoff = 0; } - - while (bytes < ctz_sz) + else { - sz = ctz_blkdatasz(sb, ctz.idx_e + 1); - mfs_ctz_rdfromoff(sb, itr_max + neg_off, path, depth, buf, - MIN(MFS_PGSZ(sb), ctz_sz - bytes)); - pg = mfs_ba_getpg(sb); - if (pg == 0) + ret = mfs_read_page(sb, buf, len, cur_pg, end_pgoff); + + if (predict_false(ret == 0)) { - ret = -ENOSPC; - goto errout_with_buf; + ret = -EINVAL; + goto errout; } - - mfs_write_page(sb, buf, MFS_PGSZ(sb), pg, 0); - bytes += MIN(MFS_PGSZ(sb), ctz_sz - bytes); } - /* TODO: Check for cases where delete, but no further data at the end. - * , which might cause an infinite loop. - */ - -errout_with_buf: - kmm_free(buf); - errout: return ret; } -int mfs_ctz_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t o_bytes, const mfs_t n_bytes, - mfs_t o_ctz_sz, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf, - FAR struct mfs_ctz_s *ctz) +int mfs_ctz_wrtnode(FAR struct mfs_sb_s * const sb, + FAR const struct mfs_node_s * const node) { - int ret = OK; - bool partial; - mfs_t partial_bytes; /* Bytes partially filled. */ - mfs_t pg; - mfs_t off; - mfs_t idx; - mfs_t bytes; - mfs_t o_pg; - mfs_t o_off; - mfs_t o_idx; - mfs_t o_rembytes; - mfs_t o_data_off; - mfs_t n_pg; - mfs_t n_data_off; - mfs_t ctz_blk_datasz; - FAR char *data; - struct mfs_ctz_s o_ctz; - struct mfs_ctz_s n_ctz; - - data = kmm_zalloc(MFS_PGSZ(sb)); - if (predict_false(data == NULL)) + int ret = OK; + bool written = false; + mfs_t prev; + mfs_t rem_sz; + mfs_t new_pg; + mfs_t cur_pg; + mfs_t cur_idx; + mfs_t cur_pgoff; + mfs_t lower; + mfs_t upper; + mfs_t upper_og; + mfs_t lower_upd; + mfs_t upper_upd; + mfs_t del_bytes; + FAR char *buf = NULL; + FAR char *tmp = NULL; + struct mfs_ctz_s ctz; + FAR struct mfs_delta_s *delta; + + /* Traverse common CTZ blocks. */ + + ctz_off2loc(sb, node->range_min, &cur_idx, &cur_pgoff); + ctz = node->path[node->depth - 1].ctz; + cur_pg = ctz_travel(sb, ctz.idx_e, ctz.pg_e, cur_idx); + + /* So, till cur_idx - 1, the CTZ blocks are common. */ + + buf = kmm_zalloc(MFS_PGSZ(sb)); + if (predict_false(buf == NULL)) { ret = -ENOMEM; goto errout; } - /* Get updated location from the journal. */ - - DEBUGASSERT(depth > 0); - mfs_jrnl_updatepath(sb, path, depth); - o_ctz = path[depth - 1].ctz; - - /* TODO: Make the traversal in reverse direction. It would cause - * a lot less traversals. + /* Initially, there might be some offset in cur_idx CTZ blocks that is + * unmodified as well. */ - ctz_off2loc(sb, data_off, &idx, &off); + tmp = buf; + mfs_read_page(sb, tmp, cur_pgoff, cur_pg, 0); + tmp += cur_pgoff; - /* Reach the common part. */ + /* Modifications. */ - if (idx != 0 && off != 0) - { - pg = ctz_travel(sb, o_ctz.idx_e, o_ctz.pg_e, idx - 1); - n_ctz.idx_e = idx - 1; - n_ctz.pg_e = pg; - } - else - { - pg = o_ctz.pg_e; - n_ctz.idx_e = 0; - n_ctz.pg_e = pg; - finfo("CTZ: %u %u %u", pg, n_ctz.idx_e, n_ctz.pg_e); - } + prev = 0; + rem_sz = node->sz; + lower = node->range_min; + del_bytes = 0; - /* Add new data from buf. */ + /* [lower, upper) range. Two pointer approach. Window gets narrower + * for every delete falling inside it. + */ - partial = false; - o_rembytes = o_ctz_sz - (data_off + o_bytes); - bytes = data_off; - if (n_bytes != 0) + while (rem_sz > 0) { - while (bytes < data_off + n_bytes) - { - n_pg = mfs_ba_getpg(sb); - if (n_pg) - { - ret = -ENOSPC; - goto errout_with_data; - } + upper = MIN(prev + lower + ctz_blkdatasz(sb, cur_idx), rem_sz); + upper_og = upper; - ctz_copyidxptrs(sb, n_ctz, idx, data); /* Handles idx == 0. */ - ctz_blk_datasz = ctz_blkdatasz(sb, idx); - - if (predict_false(off != 0)) + list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) + { + if (delta->upd == NULL) { - /* This happens at max for the first iteration of the loop. */ - - mfs_read_page(sb, data, off, - ctz_travel(sb, o_ctz.idx_e, o_ctz.pg_e, idx), 0); - bytes += off; - } + /* Delete */ - memcpy(data + off, buf + bytes, - MIN(ctz_blk_datasz - off, n_bytes - bytes)); - if (n_bytes - bytes < ctz_blk_datasz - off && o_rembytes != 0) - { - partial = true; - partial_bytes = n_bytes - bytes; + lower_upd = MAX(lower, delta->off); + upper_upd = MIN(upper, delta->off + delta->n_b); + + if (lower_upd >= upper_upd) + { + /* Skip this delta. */ + + continue; + } + else + { + del_bytes += upper_upd - lower_upd; + memmove(tmp + lower_upd, tmp + upper_upd, + upper - upper_upd); + upper -= upper_upd; + } } else { - bytes += ctz_blk_datasz - off; + /* Update */ + + ret = mfs_ctz_rdfromoff(sb, ctz, lower, upper - lower, + tmp); + if (predict_false(ret < 0)) + { + goto errout_with_buf; + } } + } - if (predict_false(off != 0)) - { - /* This happens at max for the first iteration of the loop. */ + /* rem_sz check for final write. */ - off = 0; - } + if (upper == upper_og || rem_sz == upper - lower) + { + prev = 0; + + /* Time to write a page for new CTZ list. */ - if (predict_true(!partial)) + new_pg = mfs_ba_getpg(sb); + if (predict_false(new_pg == 0)) { - mfs_write_page(sb, data, MFS_PGSZ(sb), n_pg, 0); - n_ctz.idx_e = idx; - n_ctz.pg_e = pg; + ret = -ENOSPC; + goto errout_with_buf; } - else + + ctz_copyidxptrs(sb, ctz, cur_idx, buf); + ret = mfs_write_page(sb, buf, MFS_PGSZ(sb), new_pg, 0); + if (predict_false(ret == 0)) { - /* In this case, we have a situation where there is still - * some empty area left in the page, and there is some data - * that is waiting to be fit in there, so we won't write it - * to the flash JUST yet. We'll fill in the rest of the data - * and THEN write it. - * - * It's okay to leave the loop as this case will happen, if at - * all, on the last iteration of the loop. - */ - - n_ctz.idx_e = idx; - n_ctz.pg_e = pg; - break; + ret = -EINVAL; + goto errout_with_buf; } - idx++; + memset(buf, 0, MFS_PGSZ(sb)); + tmp = buf; + cur_idx++; + + written = true; + } + else + { + tmp += upper - lower; - memset(data, 0, MFS_PGSZ(sb)); + written = false; } + + prev = upper - lower; + rem_sz -= upper - lower; + lower = upper; } - o_data_off = data_off + o_bytes; - n_data_off = data_off + n_bytes; + DEBUGASSERT(written); + + /* TODO: Need to verify for cases where the delete extends outside, etc. */ - /* Completing partially filled data, if present. */ + /* Write log. */ - if (partial) + ctz.idx_e = cur_idx; + ctz.pg_e = new_pg; + ret = mfs_jrnl_wrlog(sb, *node, ctz, node->sz); + if (predict_false(ret < 0)) { - ctz_off2loc(sb, o_data_off, &o_idx, &o_off); - o_pg = ctz_travel(sb, o_ctz.idx_e, o_ctz.pg_e, o_idx); - mfs_read_page(sb, data + partial_bytes, - ctz_blkdatasz(sb, n_ctz.idx_e) - partial_bytes, o_pg, - o_off); - mfs_write_page(sb, data, MFS_PGSZ(sb), n_ctz.pg_e, 0); - - o_data_off += partial_bytes; - n_data_off += partial_bytes; - partial_bytes = 0; - partial = false; + goto errout_with_buf; } - /* Adding old bytes in. */ - - while (o_data_off < o_ctz_sz) + if (MFS_JRNL(sb).log_cblkidx >= MFS_JRNL_LIM(sb)) { - memset(data, 0, MFS_PGSZ(sb)); - - pg = mfs_ba_getpg(sb); - if (predict_false(pg == 0)) + ret = mfs_jrnl_flush(sb); + if (predict_false(ret < 0)) { - ret = -ENOSPC; - goto errout_with_data; + goto errout_with_buf; } - - ctz_blk_datasz = ctz_blkdatasz(sb, n_ctz.idx_e + 1); - ctz_copyidxptrs(sb, n_ctz, n_ctz.idx_e + 1, data); - - mfs_ctz_rdfromoff(sb, o_data_off, path, depth, data, ctz_blk_datasz); - mfs_write_page(sb, data, MFS_PGSZ(sb), pg, 0); - - n_ctz.idx_e++; - n_ctz.pg_e = pg; - - o_data_off += ctz_blk_datasz; } - mfs_jrnl_newlog(sb, path, depth, n_ctz); - - /* path is not updated to point to the new ctz. This is upto the caller. */ - - *ctz = n_ctz; - -errout_with_data: - kmm_free(data); +errout_with_buf: + kmm_free(buf); errout: return ret; diff --git a/fs/mnemofs/mnemofs_fsobj.c b/fs/mnemofs/mnemofs_fsobj.c index aea7ccd51dbdb..1d5fbd5e07978 100644 --- a/fs/mnemofs/mnemofs_fsobj.c +++ b/fs/mnemofs/mnemofs_fsobj.c @@ -63,6 +63,7 @@ ****************************************************************************/ #include +#include #include #include "mnemofs.h" @@ -81,15 +82,27 @@ static mfs_t nobjs_in_path(FAR const char * relpath); static const char *next_child(FAR const char *relpath); +static const char *last_child(FAR const char *relpath); static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x, FAR char * const out); static FAR const char *mfs_deser_dirent(FAR const char * const in, FAR struct mfs_dirent_s * const x); +static int search_ctz_by_name(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char * const name, + const mfs_t namelen, FAR mfs_t *off, + FAR struct mfs_dirent_s **dirent); + /**************************************************************************** * Private Data ****************************************************************************/ +const struct mfs_path_s empty_fsobj = +{ + 0 +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -117,6 +130,14 @@ static mfs_t nobjs_in_path(FAR const char *relpath) { mfs_t count; + /* If mount point is "/hi", then operations on "/hi/bye" and "/hi/hello/a" + * give respective relpaths as "bye" and "hello/a". Since mnemofs counts + * the root as 1 FS object, these respectively contain 2 and 3 FS objects + * in the path. The last FS object might be a file or a directory, but + * everything else is a directory. The number of FS objects in the path + * is the depth of the FS object the path refers to. + */ + if (*relpath == 0) { return 1; @@ -124,7 +145,7 @@ static mfs_t nobjs_in_path(FAR const char *relpath) count = 2; - while (*relpath == 0) + while (*relpath != 0) { if (*relpath == '/') { @@ -138,7 +159,7 @@ static mfs_t nobjs_in_path(FAR const char *relpath) } /**************************************************************************** - * Name: nobjs_in_path + * Name: next_child * * Description: * Give the pointer to next child that appears in the path. @@ -164,7 +185,38 @@ static const char *next_child(FAR const char *relpath) relpath++; } - return NULL; + return relpath; +} + +/**************************************************************************** + * Name: next_child + * + * Description: + * Give the pointer to next child that appears in the path. + * + * Input Parameters: + * relpath - Relative Path. + * + * Returned Value: + * The pointer to the next child. This is not allocated, but points to the + * inside relpath itself. + * + ****************************************************************************/ + +static const char *last_child(FAR const char *relpath) +{ + const mfs_t len = strlen(relpath); + mfs_t i; + + for (i = len - 1; i > 0; i--) + { + if (relpath[i - 1] == '/') + { + return relpath + i; + } + } + + return relpath; } /**************************************************************************** @@ -187,9 +239,9 @@ static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x, { FAR char *o = out; - o = mfs_ser_8(x->name_hash, o); + o = mfs_ser_16(x->name_hash, o); + o = mfs_ser_16(x->mode, o); o = mfs_ser_mfs(x->sz, o); - o = mfs_ser_mfs((mfs_t) x->mode, o); o = mfs_ser_timespec(&x->st_atim, o); o = mfs_ser_timespec(&x->st_mtim, o); o = mfs_ser_timespec(&x->st_ctim, o); @@ -220,9 +272,9 @@ static FAR const char *mfs_deser_dirent(FAR const char * const in, { FAR const char *i = in; - i = mfs_deser_8(i, &x->name_hash); + i = mfs_deser_16(i, &x->name_hash); + i = mfs_deser_16(i, &x->mode); i = mfs_deser_mfs(i, &x->sz); - i = mfs_deser_mfs(i, (mfs_t *) &x->mode); i = mfs_deser_timespec(i, &x->st_atim); i = mfs_deser_timespec(i, &x->st_mtim); i = mfs_deser_timespec(i, &x->st_ctim); @@ -263,8 +315,7 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, } else if (depth == 1) { - sz = MFS_MN(sb).root_sz; - mfs_lru_updatedsz(sb, path, depth, &sz); + sz = MFS_MN(sb).root_sz; /* Updated size. */ /* Journal updated to the root creates a new master node entry. TODO * this and moving of the journal. @@ -277,218 +328,138 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, return path[depth - 1].sz; } -int mfs_get_patharr(FAR struct mfs_sb_s *const sb, - FAR const char *relpath, FAR struct mfs_path_s **path, - FAR mfs_t *depth) +bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr) { - int ret; - bool found; - bool isfile; - mfs_t sz; - mfs_t idx; - uint8_t hash; - const mfs_t len = nobjs_in_path(relpath); - FAR const char *next; - struct mfs_pitr_s pitr; - FAR struct mfs_dirent_s *dirent; + bool ret; + FAR struct mfs_dirent_s *dirent = NULL; - ret = 0; - idx = 0; - isfile = false; - found = true; + mfs_pitr_readdirent(sb, path, pitr, &dirent); + ret = (dirent->sz == 0); + mfs_free_dirent(dirent); - *path = kmm_zalloc(len * sizeof(struct mfs_ctz_s)); - if (predict_false(*path == NULL)) - { - return -ENOMEM; - } + return ret; +} - *depth = len; - (*path)[idx].ctz = MFS_MN(sb).root_ctz; - (*path)[idx].off = 0; - (*path)[idx].sz = mfs_get_fsz(sb, *path, 1); +void mfs_free_dirent(FAR struct mfs_dirent_s *dirent) +{ + kmm_free(dirent); - finfo("Path \"%s\" depth %u.", relpath, len); + finfo("Dirent freed."); +} - if (len == 1) - { - ret |= MFS_P_EXIST | MFS_P_ISDIR | MFS_ISDIR; - goto errout; - } - else if (len == 2) - { - ret |= MFS_P_EXIST | MFS_P_ISDIR; - } +bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, + FAR const struct mfs_path_s * const path, + const mfs_t depth) +{ + FAR struct mfs_ofd_s *ofd = NULL; - for (idx = 1; idx < len; idx++) + list_for_every_entry(&sb->of, ofd, struct mfs_ofd_s, list) { - mfs_pitr_init(sb, *path, idx - 1, &pitr, false); - - if (predict_false(idx == 1)) - { - next = relpath; - } - else + if (ofd->com->depth != depth) { - next = next_child(relpath); + continue; } - sz = next - relpath; - hash = mfs_arrhash(relpath, sz); + /* TODO: Ensure when an LRU's delta is flushed to the journal, the + * new location is updated in the LRU AND the open files, if it is + * open. + */ - for (; ; ) + if (mfs_path_eq(&ofd->com->path[depth - 1], &path[depth - 1])) { - mfs_pitr_readdirent(sb, &pitr, &dirent); - if (predict_false(dirent == NULL)) - { - found = false; - ret |= MFS_NEXIST; - break; - } - - if (dirent->name_hash == hash && - !strncmp(dirent->name, relpath, sz)) - { - (*path)[idx - 1].ctz = dirent->ctz; - (*path)[idx - 1].off = pitr.c_off; - (*path)[idx - 1].sz = dirent->sz; - - mfs_free_dirent(dirent); - - if (len >= 2 && idx == len - 2) - { - ret |= MFS_P_EXIST; - ret |= (S_ISDIR(dirent->mode) ? MFS_P_ISDIR : - (MFS_FINPATH | MFS_NEXIST)); - } - else if (idx == len - 1) - { - ret |= (S_ISDIR(dirent->mode) ? MFS_ISDIR : MFS_ISFILE); - } - else - { - ret |= (S_ISDIR(dirent->mode) ? 0 : - (MFS_FINPATH | MFS_NEXIST)); - } - - break; - } - - if (!S_ISDIR(dirent->mode)) - { - isfile = true; - } - - mfs_pitr_adv_dirent(&pitr, dirent); - - mfs_free_dirent(dirent); + return true; + } + } - if (isfile) - { - /* At max, only the last element is allowed to be a file. */ + return false; +} - break; - } - } +int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, + FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_dirent_s * const dirent) +{ + int ret = OK; + struct mfs_pitr_s p_pitr; + FAR struct mfs_dirent_s *p_dirent = NULL; - mfs_pitr_free(&pitr); + mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); + mfs_pitr_adv_tochild(&p_pitr, path); + mfs_pitr_readdirent(sb, path, &p_pitr, &p_dirent); - if (!found) - { - break; - } + ret = mfs_lru_del(sb, pitr->c_off, MFS_DIRENTSZ(dirent), path, depth); - relpath = next; - finfo("Next path \"%s\"", relpath); - } + mfs_free_dirent(p_dirent); + mfs_pitr_free(&p_pitr); -errout: - finfo("Path array for \"%s\", returned flags: %u.", relpath, ret); return ret; } -void mfs_free_patharr(FAR struct mfs_path_s *path) -{ - kmm_free(path); -} - -bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr) +int mfs_pitr_rm(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth) { + int ret = OK; + struct mfs_pitr_s pitr; FAR struct mfs_dirent_s *dirent = NULL; - bool ret; - mfs_pitr_readdirent(sb, pitr, &dirent); - ret = (dirent->sz == 0); + mfs_pitr_init(sb, path, depth, &pitr, true); + mfs_pitr_readdirent(sb, path, &pitr, &dirent); + ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent); mfs_free_dirent(dirent); + mfs_pitr_free(&pitr); return ret; } -void mfs_pitr_init(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, FAR struct mfs_pitr_s *pitr, - bool child) +int mfs_pitr_init(FAR const struct mfs_sb_s * const sb, + FAR const struct mfs_path_s * const path, + const mfs_t depth, FAR struct mfs_pitr_s * const pitr, + bool child) { - const uint8_t diff = child ? 1 : 0; - mfs_t p_depth; + /* Ensure updated CTZ location from the journal before this. */ + + int ret = OK; + const int diff = child ? 1 : 0; + const mfs_t p_depth = depth - diff; if (predict_false(depth < diff)) { - return; + ret = -EINVAL; + goto errout; } - p_depth = depth - diff; + pitr->c_off = 0; + pitr->depth = p_depth; - if (p_depth == 0) + if (predict_true(p_depth != 0)) { - /* Master Node */ - - pitr->sz = 0; - memset(&pitr->p, 0, sizeof(pitr->p)); + pitr->p = path[p_depth - 1]; } else { - pitr->p.ctz = path[p_depth - 1].ctz; - pitr->sz = path[p_depth - 1].sz; - } - - pitr->depth = p_depth; - pitr->c_off = 0; - - finfo("Pitr initialized for parent CTZ at (%u, %u) at" - " depth %u for file size %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->depth, pitr->sz); -} - -void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr) -{ - finfo("Pitr for CTZ (%u, %u) at depth %u freed.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->depth); - - memset(pitr, 0, sizeof(*pitr)); -} + /* 0 or gabage value is fine for master node, not required. */ -void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr) -{ - FAR struct mfs_dirent_s *dirent; + pitr->p.ctz.idx_e = 0; + pitr->p.ctz.pg_e = 0; + pitr->p.off = 0; + pitr->p.sz = 1; /* For 1 traversal to get root. */ + } - mfs_pitr_readdirent(sb, pitr, &dirent); - mfs_pitr_adv_dirent(pitr, dirent); - mfs_free_dirent(dirent); + finfo("Pitr initialized at depth %u, with CTZ (%u, %u) and size %u.", + p_depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->p.sz); - finfo("Pitr for CTZ (%u, %u) advanced to offset %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); +errout: + return ret; } -void mfs_pitr_adv_dirent(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent) +void mfs_pitr_free(FAR const struct mfs_pitr_s * const pitr) { - pitr->c_off += MFS_DIRENTSZ(dirent); - - finfo("Pitr for CTZ (%u, %u) advanced to offset %u using dirent.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); + finfo("Pitr at depth %u with CTZ (%u, %u) freed.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); } void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, @@ -496,119 +467,105 @@ void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, { pitr->c_off += off; - finfo("Pitr for CTZ (%u, %u) advanced to offset %u by offset %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off, off); + finfo("Pitr at depth %u with CTZ (%u, %u) advanced by %u to %u offset.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, off, pitr->c_off); } -void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth) +void mfs_pitr_adv_bydirent(FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_dirent_s * const dirent) { - if (pitr->depth == 0) - { - return; - } - - pitr->c_off = path[depth - 1].off; - - finfo("Pitr for CTZ (%u, %u) at depth %u advanced to offset %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, depth, path[depth - 1].off); -} - -void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr) -{ - pitr->c_off = 0; + mfs_pitr_adv_off(pitr, MFS_DIRENTSZ(dirent)); - finfo("Pitr for CTZ (%u, %u) reset.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); + finfo("Pitr at depth %u with CTZ (%u, %u) advanced by %u to %u offset.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, + MFS_DIRENTSZ(dirent), pitr->c_off); } -void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth) +void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_path_s * const path) { - finfo("Pitr for CTZ (%u, %u) syncing...", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); - - /* TODO: mfs_jrnl_updatectz(sb, &pitr->p.ctz, pitr->depth); */ - - pitr->sz = mfs_get_fsz(sb, path, depth - 1); + /* (pitr->depth + 1) - 1 is the child's index. */ - DEBUGASSERT(depth == pitr->depth); + pitr->c_off = path[pitr->depth].off; - finfo("New location is (%u, %u).", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); + finfo("Pitr at depth %u with CTZ (%u, %u) advanced to %u offset.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); } -int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, +int mfs_pitr_readdirent(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, FAR struct mfs_pitr_s * const pitr, FAR struct mfs_dirent_s **dirent) { - int ret = OK; - mfs_t sz = 0; - const mfs_t len = sizeof(struct mfs_dirent_s) - + NAME_MAX + 1; - char dirent_data[len]; - struct mfs_dirent_s *dirent_rd = NULL; - - /* No harm in reading more. The namelen will stop all the included - * unnecessary characters during deserialization, and if there are none, - * the rest will be just empty. - */ - - memset(dirent_data, 0, len); + int ret = OK; + mfs_t sz; + const mfs_t len = sizeof(struct mfs_dirent_s) \ + + NAME_MAX + 1; + char rd[len]; + FAR struct mfs_dirent_s *d = NULL; + FAR struct mfs_dirent_s *tmp = NULL; + + if (dirent == NULL) + { + return ret; + } *dirent = NULL; + memset(rd, 0, len); - dirent_rd = kmm_zalloc(len); - if (predict_false(dirent_rd == NULL)) + d = kmm_zalloc(len); + if (predict_false(d == NULL)) { + ret = -ENOMEM; goto errout; } - - if (pitr->depth == 0) + else if (pitr->c_off >= pitr->p.sz) { - dirent_rd->ctz = MFS_MN(sb).root_ctz; - dirent_rd->mode = MFS_MN(sb).root_mode; - dirent_rd->st_atim = MFS_MN(sb).root_st_atim; - dirent_rd->st_ctim = MFS_MN(sb).root_st_ctim; - dirent_rd->st_mtim = MFS_MN(sb).root_st_mtim; - dirent_rd->mode = MFS_MN(sb).root_mode; - dirent_rd->sz = MFS_MN(sb).root_sz; - dirent_rd->namelen = 1; - dirent_rd->name_hash = 0; - - memcpy(dirent_rd->name, "", 2); + goto errout_with_d; } - else + else if (pitr->depth == 0) { - mfs_lru_rdfromoff(sb, pitr->c_off, &pitr->p, pitr->depth, - dirent_data, len); - mfs_deser_dirent(dirent_data, dirent_rd); - - finfo("Got direntry with name %s", dirent_rd->name); + d->name[0] = 0; + d->namelen = 0; + d->ctz = MFS_MN(sb).root_ctz; + d->mode = MFS_MN(sb).root_mode; + d->name_hash = mfs_hash(d->name, d->namelen); + d->st_atim = MFS_MN(sb).root_st_atim; + d->st_ctim = MFS_MN(sb).root_st_ctim; + d->st_mtim = MFS_MN(sb).root_st_mtim; + d->sz = MFS_MN(sb).root_sz; + + pitr->c_off = 1; /* To prevent infinite loop. */ } - - sz = MFS_DIRENTSZ(dirent_rd); - if (dirent_rd->namelen == 0) + else { - /* Not found direntry. */ + ret = mfs_lru_rdfromoff(sb, pitr->c_off, path, pitr->depth, rd, len); + if (predict_false(ret < 0)) + { + goto errout_with_d; + } - goto errout_with_dirent_rd; + mfs_deser_dirent(rd, d); } - *dirent = kmm_zalloc(sz); - if (predict_false(*dirent == NULL)) + sz = MFS_DIRENTSZ(d); + tmp = kmm_realloc(d, sz); + if (predict_true(tmp != NULL)) { - ret = -ENOMEM; - goto errout_with_dirent_rd; + d = tmp; } - memcpy(*dirent, dirent_rd, sz); + *dirent = d; + DEBUGASSERT(pitr->depth == 0 || strcmp(d->name, "")); + finfo("Read direntry at %u offset, %u depth for CTZ (%u, %u). " \ + "Direntry name: \"%s\" with name length %u.", + pitr->c_off, pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, + d->name, d->namelen); + + return ret; -errout_with_dirent_rd: - kmm_free(dirent_rd); +errout_with_d: + kmm_free(d); if (ret < 0) { @@ -618,171 +575,370 @@ int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, { finfo("No direntry found."); } - else - { - finfo("Reading direntry done for %s.", (*dirent)->name); - } errout: return ret; } -void mfs_free_dirent(FAR struct mfs_dirent_s *dirent) +int mfs_pitr_adv(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr) { - kmm_free(dirent); + int ret = OK; + FAR struct mfs_dirent_s *dirent; - finfo("Dirent freed."); + ret = mfs_pitr_readdirent(sb, path, pitr, &dirent); + if (predict_false(ret < 0)) + { + goto errout; + } + + mfs_pitr_adv_bydirent(pitr, dirent); + mfs_free_dirent(dirent); + + finfo("Pitr for CTZ (%u, %u) advanced to offset %u.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); + +errout: + return ret; } -bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth) +static int search_ctz_by_name(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char * const name, + const mfs_t namelen, FAR mfs_t *off, + FAR struct mfs_dirent_s **dirent) { - FAR struct mfs_ofd_s *ofd = NULL; + /* NOTE: depth is of the parent here. */ - list_for_every_entry(&sb->of, ofd, struct mfs_ofd_s, list) + /* Applies LRU updates. */ + + int ret = OK; + uint16_t name_hash; + struct mfs_pitr_s pitr; + FAR struct mfs_dirent_s *nd; + bool found = false; + + *dirent = NULL; + + if (depth == 0) { - if (ofd->com->depth != depth) + DEBUGASSERT(namelen == 0); + + nd = kmm_zalloc(sizeof(struct mfs_dirent_s)); + if (predict_false(nd == NULL)) { - continue; + ret = -ENOMEM; + goto errout; } - /* TODO: Ensure when an LRU's delta is flushed to the journal, the - * new location is updated in the LRU AND the open files, if it is - * open. - */ + *off = 0; + nd->namelen = namelen; + nd->ctz = MFS_MN(sb).root_ctz; + nd->mode = MFS_MN(sb).root_mode; + nd->name_hash = mfs_hash(nd->name, nd->namelen); + nd->st_atim = MFS_MN(sb).root_st_atim; + nd->st_ctim = MFS_MN(sb).root_st_ctim; + nd->st_mtim = MFS_MN(sb).root_st_mtim; + nd->sz = MFS_MN(sb).root_sz; + + *dirent = nd; + goto errout; + } + + name_hash = mfs_hash(name, namelen); - if (ofd->com->path[depth - 1].off == path[depth - 1].off && - ofd->com->path[depth - 1].ctz.pg_e == path[depth - 1].ctz.pg_e && - ofd->com->path[depth - 1].ctz.idx_e == path[depth - 1].ctz.idx_e) + ret = mfs_lru_updatedinfo(sb, path, depth); + if (predict_false(ret < 0)) + { + goto errout; + } + + ret = mfs_pitr_init(sb, path, depth, &pitr, false); + if (predict_false(ret < 0)) + { + goto errout; + } + + for (; ; ) + { + /* Readdirent takes care of LRU updates. */ + + ret = mfs_pitr_readdirent(sb, path, &pitr, &nd); + if (predict_false(ret < 0 || nd == NULL)) { - return true; + ret = -ENONET; + goto errout; } + + if (nd->name_hash == name_hash && + !strncmp(nd->name, name, MIN(nd->namelen, namelen))) + { + found = true; + path[depth].sz = nd->sz; + path[depth].ctz = nd->ctz; + path[depth].off = pitr.c_off; + *off = pitr.c_off; + break; + } + + mfs_pitr_adv_bydirent(&pitr, nd); + mfs_free_dirent(nd); } - return false; +errout: + if (found) + { + finfo("Searched \"%.*s\" direntry inside CTZ (%u, %u) at depth %u," + " size %u.", namelen, name, path[depth - 1].ctz.idx_e, + path[depth - 1].ctz.pg_e, depth, path[depth - 1].sz); + *dirent = nd; + } + else + { + ret = -ENOENT; + finfo("Can not find requested direntry in parent. Ret: %d.", ret); + } + + return ret; } -int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, - FAR const char * const child_name, - const mode_t mode) +int mfs_get_patharr(FAR const struct mfs_sb_s * const sb, + FAR const char * relpath, FAR struct mfs_path_s **path, + FAR mfs_t *depth) { - int ret = OK; - mfs_t len; - mfs_t pg; - struct mfs_dirent_s *dirent = NULL; - struct timespec ts; + int ret = OK; + int ret_flags = 0; + mfs_t i; + mfs_t sz; + mfs_t off; + mfs_t n_objs; + mfs_t name_len; + FAR const char *cur = NULL; + FAR const char *next = NULL; + struct mfs_ctz_s ctz; + FAR struct mfs_path_s *np = NULL; + FAR struct mfs_dirent_s *dirent = NULL; + + *path = NULL; + n_objs = nobjs_in_path(relpath); + np = kmm_zalloc(n_objs * sizeof(struct mfs_path_s)); + if (predict_false(np == NULL)) + { + ret = -ENOMEM; + goto errout; + } - len = strlen(child_name); + ctz = MFS_MN(sb).root_ctz; + sz = MFS_MN(sb).root_sz; + np[0].sz = sz; + np[0].ctz = ctz; + np[0].off = 0; + cur = relpath; + next = next_child(cur); + name_len = *next == 0 ? next - cur : next - cur - 1; - dirent = kmm_zalloc(sizeof(*dirent) + len); - if (predict_false(dirent == NULL)) + if (predict_false(n_objs == 1)) { - return -ENOMEM; - } + ret_flags |= MFS_ISDIR | MFS_EXIST; - clock_gettime(CLOCK_REALTIME, &ts); + /* This will not go into the loop. */ + } + else if (predict_false(n_objs == 2)) + { + ret_flags |= MFS_P_EXIST | MFS_P_ISDIR; + } - /* TODO: Confirm if creation for directory in VFS gives true for - * S_ISDIR(). - */ + /* MFS_MN(sb).root_* is always up to date, no need for journal update. */ - pg = mfs_ba_getpg(sb); - if (predict_false(pg == 0)) + for (i = 1; i < n_objs; i++) { - return -ENOSPC; + /* np[i] is the fs object at depth i + 1. */ + + /* Need to update journal for every level in the path as, for eg., the + * child can be deleted, etc. Same goes for LRU, which is taken care of + * by search_ctz_by_name function. + */ + + ret = search_ctz_by_name(sb, np, i, cur, name_len, &off, &dirent); + if (predict_false(ret < 0)) + { + goto errout_with_ret_flags; + } + + if (i < n_objs - 2 && !S_ISDIR(dirent->mode)) + { + ret_flags |= MFS_FINPATH; + goto errout_with_ret_flags; + } + else if (i == n_objs - 2) + { + ret_flags |= MFS_P_EXIST; + if (S_ISDIR(dirent->mode)) + { + ret_flags |= MFS_P_ISDIR; + } + else + { + ret_flags |= MFS_FINPATH; + goto errout_with_ret_flags; + } + } + else /* if (i == n_objs - 1) */ + { + ret_flags |= MFS_EXIST; + if (S_ISDIR(dirent->mode)) + { + ret_flags |= MFS_ISDIR; + } + else + { + ret_flags |= MFS_ISFILE; + } + } + + np[i].ctz = dirent->ctz; + np[i].off = off; + np[i].sz = dirent->sz; + + ctz = dirent->ctz; + + mfs_free_dirent(dirent); + + cur = next; + next = next_child(cur); + name_len = *next == 0 ? next - cur : next - cur - 1; } - dirent->sz = 0; - dirent->mode = mode; - dirent->ctz.pg_e = pg; - dirent->ctz.idx_e = 0; - dirent->st_atim = ts; - dirent->st_mtim = ts; - dirent->st_ctim = ts; - dirent->namelen = len; - strncpy(dirent->name, child_name, len); + ret = ret_flags; + *depth = n_objs; + *path = np; - ret = mfs_pitr_appenddirent(sb, path, depth, pitr, dirent); - finfo("New direntry %p with name \"%s\" appended to CTZ (%u, %u) " - "at offset %u depth %u.", - dirent, dirent->name, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, - pitr->c_off, pitr->depth); + finfo("Got path array with flags %u, depth %u.", ret, n_objs); + return ret; - mfs_free_dirent(dirent); +errout_with_ret_flags: + ret = ret_flags; + *depth = n_objs; + *path = np; + /* mfs_free_patharr(np) : All callers will free np (ie. path) when done + * with it. + */ + +errout: + finfo("Got path array with flags %u, depth %u.", ret, n_objs); return ret; } +void mfs_free_patharr(FAR struct mfs_path_s *path) +{ + kmm_free(path); +} + +void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr) +{ + pitr->c_off = 0; + + finfo("Pitr for CTZ (%u, %u) reset.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); +} + int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, + FAR struct mfs_pitr_s * const pitr, FAR const struct mfs_dirent_s * const dirent) { - int ret = OK; - const mfs_t len = MFS_DIRENTSZ(dirent); - char dirent_data[len]; - struct mfs_pitr_s p_pitr; - FAR struct mfs_dirent_s *p_dirent = NULL; + /* Depth is depth of the child to be appended. */ - memset(dirent_data, 0, len); - mfs_ser_dirent(dirent, dirent_data); + int ret = OK; + const mfs_t len = MFS_DIRENTSZ(dirent); + char wd[len]; - mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); - mfs_pitr_adv_tochild(&p_pitr, path, depth - 1); - mfs_pitr_readdirent(sb, &p_pitr, &p_dirent); + if (pitr->depth == 0) + { + /* Root is the only child of the master node. */ + + ret = -EINVAL; + goto errout; + } - ret = mfs_lru_wr(sb, p_dirent->sz, len, p_dirent->sz, path, depth - 1, - dirent_data); + /* TOFO: If the parent directory is newly formed (ie. size is 0), then + * allocate space for it. This can be done better. Just allocate page when + * its created and added first to LRU, and then add a check to ensure it + * doesn't get re-allocated when written. A field like "new" would be + * helpful in the LRU node for this. + */ - mfs_free_dirent(p_dirent); - mfs_pitr_free(&p_pitr); + memset(wd, 0, len); - finfo("Appended direntry for \"%s\" at depth %u.", dirent->name, depth); + mfs_ser_dirent(dirent, wd); + ret = mfs_lru_wr(sb, pitr->p.sz, len, path, pitr->depth, wd); + if (predict_false(ret < 0)) + { + goto errout; + } +errout: return ret; } -int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent) +int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, const mfs_t depth, + FAR struct mfs_pitr_s * const pitr, + FAR const char * const relpath, const mode_t mode) { - FAR struct mfs_dirent_s *p_dirent = NULL; - struct mfs_pitr_s p_pitr; - int ret = OK; + /* Depth is depth of the child to be appended. */ - mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); - mfs_pitr_adv_tochild(&p_pitr, path, depth - 1); - mfs_pitr_readdirent(sb, &p_pitr, &p_dirent); + int ret = OK; + struct timespec ts; + FAR const char *cur = last_child(relpath); + FAR const char *next = next_child(cur); + FAR struct mfs_dirent_s *d = NULL; + const mfs_t len = *next == 0 ? next - cur : next - cur - 1; - ret = mfs_lru_del(sb, pitr->c_off, MFS_DIRENTSZ(dirent), p_dirent->sz, - path, depth); + DEBUGASSERT(depth > 0); - mfs_free_dirent(p_dirent); - mfs_pitr_free(&p_pitr); + d = kmm_zalloc(sizeof(struct mfs_dirent_s) + len); + if (predict_false(d == NULL)) + { + ret = -ENOMEM; + goto errout; + } - return ret; -} + clock_gettime(CLOCK_REALTIME, &ts); -int mfs_pitr_rm(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth) -{ - int ret = OK; - struct mfs_pitr_s pitr; - FAR struct mfs_dirent_s *dirent = NULL; + d->ctz = empty_fsobj.ctz; + d->mode = mode; + d->st_atim = ts; + d->st_mtim = ts; + d->st_ctim = ts; + d->namelen = len; + strncpy(d->name, cur, d->namelen); + d->name_hash = mfs_hash(d->name, d->namelen); + d->sz = 0; - mfs_pitr_init(sb, path, depth, &pitr, true); - mfs_pitr_readdirent(sb, &pitr, &dirent); - ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent); - mfs_free_dirent(dirent); - mfs_pitr_free(&pitr); + /* Add the new direntry in this path. */ + + path[depth - 1].ctz = d->ctz; + path[depth - 1].off = pitr->p.sz; + path[depth - 1].sz = d->sz; + + ret = mfs_pitr_appenddirent(sb, path, depth, pitr, d); + if (predict_false(ret < 0)) + { + goto errout_with_d; + } + + finfo("Direntry appended to Pitr with %u depth, and CTZ (%u, %u). " \ + "Direntry name: \"%.*s\" with name length %u at offset %u.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, d->namelen, + d->name, d->namelen, path[depth - 1].off); +errout_with_d: + mfs_free_dirent(d); + +errout: return ret; } diff --git a/fs/mnemofs/mnemofs_journal.c b/fs/mnemofs/mnemofs_journal.c index 2fdc6d2d1bc2b..907bb6f1ea233 100644 --- a/fs/mnemofs/mnemofs_journal.c +++ b/fs/mnemofs/mnemofs_journal.c @@ -87,6 +87,11 @@ * Pre-processor Definitions ****************************************************************************/ +#define MFS_JRNL_SUFFIXSZ (8 + 2) /* 8 byte magic sequence + no. of blks */ +#define MFS_LOGSZ(depth) (sizeof(mfs_t) * 2 + sizeof(struct mfs_ctz_s) + \ + sizeof(struct mfs_path_s) * depth + \ + sizeof(struct timespec) * 3 + sizeof(uint16_t)) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -97,26 +102,35 @@ * search methods of higher functions. */ -/* There is a byte-long hash that follows this on-flash. */ +/* New journal log structure being phased in. */ struct jrnl_log_s { - mfs_t depth; - struct mfs_ctz_s new; - FAR struct mfs_ctz_s path[]; + /* A field denoting the size of the below elements is added here on-flash. + */ + + mfs_t depth; + mfs_t sz_new; + struct mfs_ctz_s loc_new; + struct timespec st_mtim_new; + struct timespec st_atim_new; + struct timespec st_ctim_new; + FAR struct mfs_path_s *path; + uint16_t hash; }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static int jrnl_wrlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz); -static int jrnl_rdlog(FAR const struct mfs_sb_s * const sb, mfs_t pg, - mfs_t idx, FAR mfs_t *new_pg, FAR mfs_t *new_idx, - FAR struct jrnl_log_s **log); -static void jrnl_log_free(FAR struct jrnl_log_s *log); +static int jrnl_rdlog(FAR const struct mfs_sb_s *const sb, + FAR mfs_t *blkidx, FAR mfs_t *pg_in_blk, + FAR struct jrnl_log_s *log); + +FAR static const char *deser_log(FAR const char * const in, + FAR struct jrnl_log_s * const x); +FAR static char *ser_log(FAR const struct jrnl_log_s * const x, + FAR char * const out); /**************************************************************************** * Private Data @@ -131,102 +145,143 @@ static void jrnl_log_free(FAR struct jrnl_log_s *log); ****************************************************************************/ /**************************************************************************** - * Name: jrnl_wrlog + * Name: jrnl_rdlog * * Description: - * Appends a log to the journal. + * Read a log to the journal from given location, and update location to + * point to next log location. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Length of path. - * new_ctz - The updated location. + * sb - Superblock instance of the device. + * blkidx - Journal Block Index of the current block. + * pg_in_blk - Page offset in the block. + * log - To populate with the log. * * Returned Value: * 0 - OK * < 0 - Error * * Assumptions/Limitations: - * Assumes the CTZ list to be updated is `path[depth - 1].ctz`. + * This function does NOT care about start of the journal, or even, if + * the initial requested area is inside the journal. It will malfunction + * if not used properly. Usually this is used in an iterative manner, and + * hence the first time blkidx and pg_in_blk are initialized, they should + * be derived from the values in MFS_JRNL(sb) respectively. + * + * This updates the blkidx and pg_in_blk to point to the next log, and + * returns an -ENOSPC when end of journal is reached in traversal. + * + * Free the log after use. * ****************************************************************************/ -static int jrnl_wrlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz) +static int jrnl_rdlog(FAR const struct mfs_sb_s *const sb, + FAR mfs_t *blkidx, FAR mfs_t *pg_in_blk, + FAR struct jrnl_log_s *log) { - int ret = OK; - mfs_t i; - mfs_t pg; - mfs_t idx; - mfs_t sz; - mfs_t blk; - mfs_t n_pgs; - mfs_t rem_sz; - FAR char *tmp; - FAR char *buf = NULL; + int ret = OK; + char tmp[4]; + mfs_t i; + mfs_t len; + mfs_t n_pgs; + mfs_t rd_sz; + mfs_t log_sz; + mfs_t jrnl_pg; + mfs_t jrnl_blk; + FAR char *buf = NULL; + FAR char *buftmp = NULL; - /* FUTURE TODO: Group logs together. Common hash and a prefix for number - * of logs together. - */ + DEBUGASSERT(*pg_in_blk % MFS_PGSZ(sb) == 0); - /* Serialize. */ + jrnl_blk = mfs_jrnl_blkidx2blk(sb, *blkidx); + jrnl_pg = MFS_BLK2PG(sb, jrnl_blk) + *pg_in_blk; - sz = sizeof(struct jrnl_log_s) + depth * sizeof(struct mfs_ctz_s) + 1; - buf = kmm_zalloc(sz); - if (predict_false(buf == NULL)) + /* First 4 bytes contain the size of the entire log. */ + + ret = mfs_read_page(sb, tmp, 4, jrnl_pg, 0); + if (predict_false(ret < 0)) { - ret = -ENOMEM; goto errout; } - tmp = buf; - tmp = mfs_ser_mfs(depth, tmp); - tmp = mfs_ser_ctz(&new_ctz, tmp); - for (i = 0; i < depth; i++) + mfs_deser_mfs(tmp, &log_sz); + n_pgs = MFS_CEILDIVIDE(log_sz, MFS_PGSZ(sb)); + + buf = kmm_zalloc(log_sz); + if (predict_false(buf == NULL)) { - tmp = mfs_ser_ctz(&path[i].ctz, tmp); + ret = -ENOMEM; + goto errout; } - tmp = mfs_ser_8(mfs_arrhash(buf, sz - 1), tmp); /* Hash */ + buftmp = buf; + rd_sz = 0; + for (i = 0; i < n_pgs && rd_sz < log_sz; i++) + { + /* This if-statement exists to remove calculation behind + * MIN(MFS_PGSZ(sb), log_sz - rd_sz) + */ - /* Write. */ + if (i == 0 && i != n_pgs - 1) + { + ret = mfs_read_page(sb, buftmp, MFS_PGSZ(sb), jrnl_pg, + sizeof(mfs_t)); + len = MFS_PGSZ(sb); + } + else if (i == 0) + { + ret = mfs_read_page(sb, buftmp, log_sz, jrnl_pg, sizeof(mfs_t)); + len = log_sz; + } + else if (i == n_pgs - 1) + { + ret = mfs_read_page(sb, buftmp, log_sz - rd_sz, jrnl_pg, 0); + len = log_sz - rd_sz; + } + else + { + ret = mfs_read_page(sb, buftmp, MFS_PGSZ(sb), jrnl_pg, 0); + len = MFS_PGSZ(sb); + } - pg = MFS_JRNL(sb).log_cpg; - idx = MFS_JRNL(sb).log_cblkidx; - blk = MFS_PG2BLK(sb, pg); - n_pgs = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); /* Ceil */ - tmp = buf; + buftmp += len; + rd_sz += len; - for (i = 0; i < n_pgs; i++) - { - rem_sz = MIN(MFS_PGSZ(sb), buf + sz - tmp); - ret = mfs_write_page(sb, tmp, rem_sz, pg, 0); - if (predict_false(ret < 0)) + if (predict_false(ret == 0)) { + ret = -EINVAL; /* TODO: Need to check when this occurs. */ goto errout_with_buf; } - pg++; + /* Move to next block if needed. */ - if (pg - MFS_BLK2PG(sb, blk) >= MFS_PGINBLK(sb)) + jrnl_pg++; + if (jrnl_pg - MFS_BLK2PG(sb, jrnl_blk) >= MFS_PGINBLK(sb)) { - idx++; - if (idx >= MFS_JRNL(sb).n_blks) + (*blkidx)++; + + if (*blkidx >= MFS_JRNL(sb).n_blks) { - /* TODO: Time for journal flushing and moving. */ + /* Not finished reading log yet, and the journal is over. */ + + ret = -ENOSPC; + goto errout_with_buf; } - blk = mfs_jrnl_blkidx2blk(sb, idx); - pg = MFS_BLK2PG(sb, blk); + jrnl_blk = mfs_jrnl_blkidx2blk(sb, *blkidx); + jrnl_pg = MFS_BLK2PG(sb, jrnl_blk); } + } - tmp += rem_sz; + if (predict_false(deser_log(buf, log) == NULL)) + { + ret = -ENOMEM; + goto errout_with_buf; } - MFS_JRNL(sb).log_cpg = pg; - MFS_JRNL(sb).log_cblkidx = idx; - MFS_JRNL(sb).n_logs += 1; + /* blkidx has been up to date throughout the program. */ + + *pg_in_blk = jrnl_pg - MFS_BLK2PG(sb, jrnl_blk); errout_with_buf: kmm_free(buf); @@ -236,217 +291,128 @@ static int jrnl_wrlog(FAR struct mfs_sb_s * const sb, } /**************************************************************************** - * Name: jrnl_rdlog + * Name: ser_log * * Description: - * Read a log to the journal from given location. + * Serialize a log. * * Input Parameters: - * sb - Superblock instance of the device. - * pg - Page number of the start of the log. - * idx - Index of the start of the log. - * new_pg - Page number of the start of the next log. - * new_idx - Index of the start of the next log. - * log - To populate with the log. + * n - Log to serialize + * out - Output array where to serialize. * * Returned Value: - * 0 - OK - * < 0 - Error + * Pointer to byte after the end of serialized value. * * Assumptions/Limitations: - * This assumes that at any possibly attainable locations in the journal, - * there will atleast be 4 bytes of data left in that page to read. + * This assumes the out buffer has enough space to hold the inline path. * - * Everything stored in the journal blocks is multiple of 4, and any block - * size is a power of 2, so any block size greater than 4 should also be a - * multiple of 4. - * - * Free the log after use. + * This doesn't require the hash to be pre-calculated. * ****************************************************************************/ -static int jrnl_rdlog(FAR const struct mfs_sb_s * const sb, mfs_t pg, - mfs_t idx, FAR mfs_t *new_pg, FAR mfs_t *new_idx, - FAR struct jrnl_log_s **log) +FAR static char *ser_log(FAR const struct jrnl_log_s * const x, + FAR char * const out) { - int ret = OK; - char buftmp[4]; - mfs_t n_pgs; - mfs_t i; - mfs_t sz; - mfs_t blk; - mfs_t depth; - mfs_t rem_sz; - uint8_t hash; - FAR char *buf = NULL; - FAR char *tmp; - FAR const char *tmp2; - - blk = MFS_PG2BLK(sb, pg); - - /* Read depth. */ - - mfs_read_page(sb, buftmp, 5, pg, 0); - mfs_deser_mfs(buftmp, &depth); - - sz = sizeof(struct jrnl_log_s) + (depth * sizeof(struct mfs_ctz_s)) + 1; - buf = kmm_zalloc(sz); - if (predict_false(buf == NULL)) - { - ret = -ENOMEM; - goto errout; - } - - *log = kmm_zalloc(sz - 1); - if (predict_false(*log == NULL)) - { - goto errout_with_buf; - } - - /* Read the log. */ + char *o = out; + mfs_t i = 0; - n_pgs = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); - tmp = buf; + o = mfs_ser_mfs(x->depth, o); + o = mfs_ser_mfs(x->sz_new, o); + o = mfs_ser_ctz(&x->loc_new, o); + o = mfs_ser_timespec(&x->st_mtim_new, o); + o = mfs_ser_timespec(&x->st_atim_new, o); + o = mfs_ser_timespec(&x->st_ctim_new, o); - for (i = 0; i < n_pgs; i++) + for (i = 0; i < x->depth; i++) { - rem_sz = MIN(MFS_PGSZ(sb), buf + sz - tmp); - ret = mfs_read_page(sb, tmp, rem_sz, pg, 0); - if (predict_false(ret < 0)) - { - goto errout_with_log; - } + o = mfs_ser_path(&x->path[i], o); + } - pg++; + o = mfs_ser_16(mfs_hash(out, o - out), o); + return o; +} - if (pg - MFS_BLK2PG(sb, blk) >= MFS_PGINBLK(sb)) - { - idx++; - if (idx >= MFS_JRNL(sb).n_blks) - { - /* TODO: Time for journal flushing and moving. */ - } +/**************************************************************************** + * Name: deser_log + * + * Description: + * Deserialize a log. + * + * Input Parameters: + * in - Input array from where to deserialize. + * n - Log to deserialize + * + * Returned Value: + * NULL - Error. + * Pointer to byte after the end of serialized value. + * + * Assumptions/Limitations: + * This allocates space for the path, and the log should freed after use. + * + ****************************************************************************/ - blk = mfs_jrnl_blkidx2blk(sb, idx); - pg = MFS_BLK2PG(sb, blk); - } +FAR static const char *deser_log(FAR const char * const in, + FAR struct jrnl_log_s * const x) +{ + mfs_t k = 0; + const char *i = in; - tmp += rem_sz; - } + i = mfs_deser_mfs(i, &x->depth); + i = mfs_deser_mfs(i, &x->sz_new); + i = mfs_deser_ctz(i, &x->loc_new); + i = mfs_deser_timespec(i, &x->st_mtim_new); + i = mfs_deser_timespec(i, &x->st_atim_new); + i = mfs_deser_timespec(i, &x->st_ctim_new); - /* Deserialize */ + /* Allocates path. Deallocate using mfs_jrnl_log_free. */ - tmp2 = buf; - tmp2 = mfs_deser_ctz(tmp2, &(*log)->new); - for (i = 0; i < depth; i++) + x->path = kmm_zalloc(sizeof(struct jrnl_log_s) * x->depth); + if (predict_false(x->path == NULL)) { - tmp2 = mfs_deser_ctz(tmp2, &(*log)->path[i]); + return NULL; } - tmp2 = mfs_deser_8(tmp2, &hash); - - if (hash != mfs_arrhash(buf, sz - 1)) + for (k = 0; k < x->depth; k++) { - ret = -EINVAL; - goto errout_with_log; + i = mfs_deser_path(i, &x->path[k]); } - *new_pg = pg; - *new_idx = idx; - - kmm_free(buf); - return ret; - -errout_with_log: - kmm_free(*log); - *log = NULL; - -errout_with_buf: - kmm_free(buf); - -errout: - return ret; + i = mfs_deser_16(i, &x->hash); + return i; } /**************************************************************************** * Name: jrnl_log_free * * Description: - * Free a log. + * Free the log. * * Input Parameters: - * log - Journal log. + * log - Log + * + * Assumptions/Limitations: + * This allocates space for the path, and the log should freed after use. * ****************************************************************************/ -static void jrnl_log_free(FAR struct jrnl_log_s *log) +static void jrnl_log_free(FAR const struct jrnl_log_s * const log) { - kmm_free(log); + free(log->path); } /**************************************************************************** * Public Functions ****************************************************************************/ -int mfs_jrnl_newlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz) -{ - return jrnl_wrlog(sb, path, depth, new_ctz); -} - -int mfs_jrnl_updatepath(FAR const struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth) -{ - int ret = OK; - mfs_t k; - mfs_t pg; - mfs_t idx; - struct jrnl_log_s *log; - - idx = MFS_JRNL(sb).log_sblkidx; - pg = MFS_JRNL(sb).log_spg; - - for (k = 0; k < MFS_JRNL(sb).n_logs; k++) - { - ret = jrnl_rdlog(sb, pg, idx, &pg, &idx, &log); - if (predict_false(ret < 0)) - { - return ret; - } - - if (log->depth > depth) - { - continue; - } - - if (depth == 0 || - (log->path[log->depth - 1].pg_e == path[log->depth - 1].ctz.pg_e && - log->path[log->depth - 1].idx_e == path[log->depth - 1].ctz.idx_e)) - { - path[log->depth].ctz = log->new; - } - - jrnl_log_free(log); - } - - /* TODO: Create an update offset function in ctz.c to update the offsets - * of path. - */ - - return ret; -} - int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk) { - mfs_t pg; - FAR char *buf = NULL; - char buftmp[2]; - int ret = OK; - mfs_t sz; - mfs_t idx; - FAR struct jrnl_log_s *log = NULL; + char buftmp[2]; + int ret = OK; + mfs_t sz; + mfs_t blkidx; + mfs_t pg_in_blk; + FAR char *buf = NULL; + FAR struct jrnl_log_s *log = NULL; /* Magic sequence is already used to find the block, so not required. */ @@ -459,28 +425,44 @@ int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk) goto errout; } - sz = 8 + 2 + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); - pg = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); + sz = MFS_JRNL_SUFFIXSZ + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); - MFS_JRNL(sb).log_cpg = pg; - MFS_JRNL(sb).log_cblkidx = 0; + MFS_JRNL(sb).log_cpg = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); MFS_JRNL(sb).log_spg = MFS_JRNL(sb).log_cpg; + MFS_JRNL(sb).log_cblkidx = 0; MFS_JRNL(sb).log_sblkidx = MFS_JRNL(sb).log_cblkidx; MFS_JRNL(sb).jrnlarr_pg = 0; - MFS_JRNL(sb).jrnlarr_pgoff = 8 + 2; + MFS_JRNL(sb).jrnlarr_pgoff = MFS_JRNL_SUFFIXSZ; /* Number of logs */ - idx = 0; MFS_JRNL(sb).n_logs = 0; - while (idx < MFS_JRNL(sb).n_logs) + blkidx = MFS_JRNL(sb).log_sblkidx; + pg_in_blk = MFS_JRNL(sb).log_spg % MFS_PGINBLK(sb); + + while (true) { - jrnl_rdlog(sb, pg, idx, &pg, &idx, &log); + /* TODO: Update this to new read log. */ + + ret = jrnl_rdlog(sb, &blkidx, &pg_in_blk, log); + if (predict_false(ret < 0 && ret != -ENOSPC)) + { + goto errout; + } + else if (ret == -ENOSPC) + { + ret = OK; + break; + } - /* Assumes checking the depth is enough to check if it's empty. */ + /* Assumes checking the depth is enough to check if it's empty, as + * theoretically there are no blocks with depth 0, as root has a + * depth of 1. + */ - if (log->depth == 0) + if (!log || log->depth == 0) { + DEBUGASSERT(!log || log->path == NULL); break; } @@ -501,13 +483,6 @@ int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk) return ret; } -void mfs_jrnl_free(FAR struct mfs_sb_s * const sb) -{ - /* TODO: Flush entire journal here. */ - - finfo("Journal Freed."); -} - int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) { int i; @@ -524,7 +499,7 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) /* Write magic sequence, size of jrnlarr, and then the jrnlarr. */ - sz = 8 + 2 + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); + sz = MFS_JRNL_SUFFIXSZ + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); n_pgs = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); buf = kmm_zalloc(sz); @@ -606,7 +581,7 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) MFS_JRNL(sb).log_spg = MFS_JRNL(sb).log_cpg; MFS_JRNL(sb).log_sblkidx = MFS_JRNL(sb).log_cblkidx; MFS_JRNL(sb).jrnlarr_pg = MFS_BLK2PG(sb, blk); - MFS_JRNL(sb).jrnlarr_pgoff = 8 + 2; + MFS_JRNL(sb).jrnlarr_pgoff = MFS_JRNL_SUFFIXSZ; MFS_JRNL(sb).n_blks = CONFIG_MNEMOFS_JOURNAL_NBLKS; MFS_JRNL(sb).mblk1 = blk1; MFS_JRNL(sb).mblk2 = blk2; @@ -629,14 +604,20 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) return ret; } +void mfs_jrnl_free(FAR struct mfs_sb_s * const sb) +{ + mfs_jrnl_flush(sb); + finfo("Journal Freed."); +} + mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, const mfs_t blk_idx) { - int ret = OK; + int ret = OK; mfs_t pg; - mfs_t pgoff; - mfs_t blk; mfs_t idx; + mfs_t blk; + mfs_t pgoff; char buf[4]; pg = MFS_JRNL(sb).jrnlarr_pg; @@ -669,3 +650,177 @@ mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, return idx; } + +int mfs_jrnl_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth) +{ + int ret = OK; + mfs_t blkidx; + mfs_t counter = 0; + mfs_t pg_in_block; + struct jrnl_log_s tmplog; + + /* TODO: Allow optional filling of updated timestamps, etc. */ + + DEBUGASSERT(depth > 0); + + blkidx = MFS_JRNL(sb).log_sblkidx; + pg_in_block = MFS_JRNL(sb).log_spg % MFS_PGINBLK(sb); + + while (blkidx < MFS_JRNL(sb).n_blks && counter < MFS_JRNL(sb).n_logs) + { + ret = jrnl_rdlog(sb, &blkidx, &pg_in_block, &tmplog); + if (predict_false(ret < 0 && ret != -ENOSPC)) + { + goto errout; + } + else if (ret == -ENOSPC) + { + break; + } + + DEBUGASSERT(tmplog.depth > 0); + + if (tmplog.depth > depth) + { + /* Not suitable. */ + } + else + { + DEBUGASSERT(tmplog.depth > 0); + + if (mfs_path_eq(&tmplog.path[tmplog.depth - 1], + &path[tmplog.depth - 1])) + { + path[tmplog.depth - 1].ctz = tmplog.loc_new; + path[tmplog.depth - 1].sz = tmplog.sz_new; + } + } + + jrnl_log_free(&tmplog); + counter++; + } + +errout: + return ret; +} + +int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb, + const struct mfs_node_s node, + const struct mfs_ctz_s loc_new, const mfs_t sz_new) +{ + int ret = OK; + mfs_t i; + mfs_t n_pgs; + mfs_t wr_sz; + mfs_t jrnl_pg; + mfs_t jrnl_blk; + FAR char *buf = NULL; + FAR char *tmp = NULL; + const mfs_t log_sz = sizeof(mfs_t) + MFS_LOGSZ(node.depth); + struct jrnl_log_s log; + + buf = kmm_zalloc(log_sz); /* For size before log. */ + if (predict_false(buf == NULL)) + { + ret = -ENOMEM; + goto errout; + } + + /* Serialize */ + + log.depth = node.depth; + log.sz_new = node.depth; + log.loc_new = loc_new; + log.st_mtim_new = node.st_mtim; + log.st_atim_new = node.st_atim; + log.st_ctim_new = node.st_ctim; + log.path = node.path; /* Fine as temporarily usage. */ + + tmp = buf; + tmp = mfs_ser_mfs(log_sz - sizeof(mfs_t), tmp); + tmp = ser_log(&log, tmp); + + /* Store */ + + n_pgs = MFS_CEILDIVIDE(log_sz, MFS_PGSZ(sb)); + jrnl_blk = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).log_cblkidx); + jrnl_pg = MFS_JRNL(sb).log_cpg; + tmp = buf; + wr_sz = 0; + for (i = 0; i < n_pgs && wr_sz < log_sz; i++) + { + /* This if-statement exists to remove calculation behind + * MIN(MFS_PGSZ(sb), log_sz - wr_sz) + */ + + if (i == 0 && i == n_pgs - 1) + { + ret = mfs_write_page(sb, tmp, log_sz, jrnl_pg, 0); + wr_sz += log_sz; + tmp += log_sz; + } + else if (i == 0) + { + ret = mfs_write_page(sb, tmp, MFS_PGSZ(sb), jrnl_pg, 0); + wr_sz += MFS_PGSZ(sb); + tmp += MFS_PGSZ(sb); + } + else if (i == n_pgs - 1) + { + ret = mfs_write_page(sb, tmp, log_sz - wr_sz, jrnl_pg, 0); + wr_sz += MFS_PGSZ(sb); + tmp += MFS_PGSZ(sb); + } + else + { + ret = mfs_write_page(sb, tmp, MFS_PGSZ(sb), jrnl_pg, 0); + wr_sz += MFS_PGSZ(sb); + tmp += MFS_PGSZ(sb); + } + + if (predict_false(ret == 0)) + { + ret = -EINVAL; + goto errout_with_buf; + } + + /* Move to next block if needed. */ + + jrnl_pg++; + if (jrnl_pg - MFS_BLK2PG(sb, jrnl_blk) == MFS_PGINBLK(sb)) + { + MFS_JRNL(sb).log_cblkidx++; + + if (MFS_JRNL(sb).log_cblkidx == MFS_JRNL(sb).n_blks) + { + /* Not finished reading log yet, and the journal is over. */ + + ret = -ENOSPC; + goto errout_with_buf; + } + + jrnl_blk = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).log_cblkidx); + jrnl_pg = MFS_BLK2PG(sb, jrnl_blk); + } + } + + /* MFS_JRNL(sb).log_cblkidx is up to date */ + + MFS_JRNL(sb).log_cpg = jrnl_pg; + MFS_JRNL(sb).n_logs++; + +errout_with_buf: + kmm_free(buf); + +errout: + return ret; +} + +int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb) +{ + /* TODO */ + + return OK; +} diff --git a/fs/mnemofs/mnemofs_lru.c b/fs/mnemofs/mnemofs_lru.c index a1b032e44dd54..a0965e439c301 100644 --- a/fs/mnemofs/mnemofs_lru.c +++ b/fs/mnemofs/mnemofs_lru.c @@ -93,15 +93,22 @@ enum * Private Function Prototypes ****************************************************************************/ -static void lru_nodesearch(FAR struct mfs_sb_s * const sb, +static void lru_nodesearch(FAR const struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, const mfs_t depth, FAR struct mfs_node_s **node); static bool lru_islrufull(FAR struct mfs_sb_s * const sb); static bool lru_isnodefull(FAR struct mfs_node_s *node); -static int lru_nodeflush(FAR struct mfs_sb_s * const sb, +static int lru_nodeflush(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR struct mfs_node_s *node, + bool clean_node); +static int lru_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, + mfs_t bytes, int op, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char *buf); +static int lru_updatesz(FAR struct mfs_sb_s * sb, FAR struct mfs_path_s * const path, - const mfs_t depth, const mfs_t ctz_sz, - FAR struct mfs_node_s *node, bool clean_node); + const mfs_t depth, const mfs_t new_sz); /**************************************************************************** * Private Data @@ -129,58 +136,69 @@ static int lru_nodeflush(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -static void lru_nodesearch(FAR struct mfs_sb_s * const sb, +static void lru_nodesearch(FAR const struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, const mfs_t depth, FAR struct mfs_node_s **node) { - bool found; - mfs_t i; + bool found = false; + mfs_t i; FAR struct mfs_node_s *n; *node = NULL; + list_for_every_entry(&MFS_LRU(sb), n, struct mfs_node_s, list) { - if (n == NULL) - { - break; - } + /* We need this loop to specifically check the parents in case these + * entries are all new, and have not been allocated any pages for + * being stored in the flash. Also we know that the root (depth 1) will + * be at least common in their paths. + */ + + DEBUGASSERT(depth > 0); - found = true; if (n->depth != depth) { continue; } - if (depth != 0) + found = true; + for (i = n->depth; i >= 1 && found; i--) { - for (i = depth - 1; i + 1 > 0; i--) /* i + 1 prevents underflow. */ + if (path[i - 1].ctz.idx_e == 0 && path[i - 1].ctz.pg_e == 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz) && + n->path[i - 1].off == path[i - 1].off) { - if (n->path[i].off == path[i].off && - n->path[i].ctz.idx_e == path[i].ctz.idx_e && - n->path[i].ctz.pg_e == path[i].ctz.pg_e) - { - /* OK */ - } - else - { - found = false; - break; - } + /* OK */ + } + else if (path[i - 1].ctz.pg_e != 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz)) + { + /* OK */ + } + else + { + found = false; } } if (found) { - finfo("Node search ended with match of node %p at depth %u" - " for CTZ of %u original size with range [%u, %u).", n, - n->depth, n->sz, n->range_min, n->range_max); *node = n; - return; + break; } } - *node = NULL; - finfo("Node search ended without match."); + if (found) + { + finfo("Node search ended with match of node %p at depth %u" + " for CTZ of %u size with range [%u, %u).", n, n->depth, n->sz, + n->range_min, n->range_max); + } + else + { + finfo("Node search ended without match."); + *node = NULL; + } } /**************************************************************************** @@ -190,7 +208,7 @@ static void lru_nodesearch(FAR struct mfs_sb_s * const sb, * Check whether the number of nodes in the LRU has reaches its limit. * * Input Parameters: - * sb - Superblock instance of the device. + * sb - Superblock instance of the device. * * Returned Value: * true - LRU is full @@ -223,6 +241,17 @@ static bool lru_isnodefull(FAR struct mfs_node_s *node) return node->n_list == CONFIG_MNEMOFS_NLRUDELTA; } +/**************************************************************************** + * Name: lru_free_delta + * + * Description: + * Free a node's delta. + * + * Input Parameters: + * delta - LRU delta. + * + ****************************************************************************/ + static void lru_free_delta(FAR struct mfs_delta_s *delta) { kmm_free(delta->upd); @@ -252,10 +281,10 @@ static void lru_free_delta(FAR struct mfs_delta_s *delta) static int lru_nodeflush(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, - const mfs_t depth, const mfs_t ctz_sz, - FAR struct mfs_node_s *node, bool clean_node) + const mfs_t depth, FAR struct mfs_node_s *node, + bool clean_node) { - int ret = OK; + int ret = OK; FAR struct mfs_delta_s *delta = NULL; FAR struct mfs_delta_s *tmp = NULL; @@ -264,8 +293,9 @@ static int lru_nodeflush(FAR struct mfs_sb_s * const sb, return -ENOMEM; } - ret = mfs_ctz_nwrtooff(sb, node, path, depth, ctz_sz, - &path[depth - 1].ctz); + /* TODO: Implement effct of clean_node. */ + + ret = mfs_ctz_wrtnode(sb, node); if (predict_false(ret < 0)) { goto errout; @@ -289,13 +319,36 @@ static int lru_nodeflush(FAR struct mfs_sb_s * const sb, return ret; } -static int lru_wrtooff(FAR struct mfs_sb_s * const sb, - const mfs_t data_off, mfs_t bytes, mfs_t ctz_sz, - int op, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf) +/**************************************************************************** + * Name: lru_wrtooff + * + * Description: + * Write to offset in LRU. + * + * Input Parameters: + * sb - Superblock instance of the device. + * data_off - Offset into the data in the CTZ skip list. + * bytes - Number of bytes to write. + * ctz_sz - Size of the CTZ skip list. + * op - Operation (MFS_LRU_UPD or MFS_LRU_DEL). + * path - CTZ representation of the path. + * depth - Depth of path. + * buf - Buffer containing data. + * + * Returned Value: + * 0 - OK + * < 0 - Error + * + ****************************************************************************/ + +static int lru_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, + mfs_t bytes, int op, + FAR struct mfs_path_s * const path, const mfs_t depth, + FAR const char *buf) { - int ret = OK; - bool found = true; + int ret = OK; + bool found = true; + mfs_t old_sz; FAR struct mfs_node_s *node = NULL; FAR struct mfs_node_s *last_node = NULL; FAR struct mfs_delta_s *delta = NULL; @@ -304,14 +357,23 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, if (node == NULL) { - node = kmm_zalloc(sizeof(*node) + (depth * sizeof(struct mfs_path_s))); + node = kmm_zalloc(sizeof(*node)); if (predict_false(node == NULL)) { + found = false; ret = -ENOMEM; goto errout; } - node->sz = ctz_sz; + node->path = kmm_zalloc(depth * sizeof(struct mfs_path_s)); + if (predict_false(node->path == NULL)) + { + found = false; + ret = -ENOMEM; + goto errout_with_node; + } + + node->sz = path[depth - 1].sz; node->depth = depth; node->n_list = 0; node->range_max = 0; @@ -320,7 +382,7 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, memcpy(node->path, path, depth * sizeof(struct mfs_path_s)); found = false; - finfo("Node not found, allocated, ready to be inserted into LRU."); + finfo("Node not found. Allocated at %p.", node); } if (!found) @@ -345,7 +407,7 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, { /* Node flush writes to the flash and journal. */ - ret = lru_nodeflush(sb, path, depth, ctz_sz, node, false); + ret = lru_nodeflush(sb, path, depth, node, false); if (predict_false(ret < 0)) { goto errout_with_node; @@ -373,7 +435,8 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, goto errout_with_delta; } - finfo("Delta is of the update type, has %u bytes of updates." , bytes); + finfo("Delta is of the update type, has %u bytes at offset %u.", + bytes, data_off); } delta->n_b = bytes; @@ -385,21 +448,37 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, } node->n_list++; - node->range_min = MIN(node->range_min, data_off); - node->range_max = MAX(node->range_max, data_off + bytes); + node->range_min = MIN(node->range_min, data_off); + node->range_max = MAX(node->range_max, data_off + bytes); + + old_sz = node->sz; + node->sz = MAX(node->range_max, path[depth - 1].sz); + node->path[node->depth - 1].sz = node->sz; + + if (old_sz != node->sz) + { + ret = lru_updatesz(sb, node->path, node->depth, node->sz); + if (predict_false(ret < 0)) + { + goto errout_with_delta; + } + } - finfo("Delta attached to node. Now there are %lu nodes and the node has" - " %lu deltas. Node with range [%u, %u).", list_length(&MFS_LRU(sb)), - list_length(&node->delta), node->range_min, node->range_max); + finfo("Delta attached to node %p. Now there are %lu nodes and the node has" + " %lu deltas. Node with range [%u, %u).", node, + list_length(&MFS_LRU(sb)), list_length(&node->delta), + node->range_min, node->range_max); return ret; errout_with_delta: + list_delete(&delta->list); kmm_free(delta); errout_with_node: if (!found && node != NULL) { + list_delete(&node->list); kmm_free(node); } @@ -407,13 +486,106 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, return ret; } +/**************************************************************************** + * Name: lru_updatesz + * + * Description: + * Updates size of an fs object in its parent. + * + * Input Parameters: + * sb - Superblock instance of the device. + * path - CTZ representation of the path. + * depth - Depth of path. + * new_sz - New size + * + * Returned Value: + * 0 - OK + * < 0 - Error + * + * Assumptions/Limitations: + * Adds an entry for the target's parent to update the child's size, and + * updates the size in path of everyone that has this child. + * + ****************************************************************************/ + +static int lru_updatesz(FAR struct mfs_sb_s * sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, const mfs_t new_sz) +{ + int ret = OK; + struct mfs_node_s *n = NULL; + mfs_t i; + bool found; + char buf[sizeof(mfs_t)]; + + DEBUGASSERT(depth > 0); + + list_for_every_entry(&MFS_LRU(sb), n, struct mfs_node_s, list) + { + if (n->depth < depth) + { + continue; + } + + found = false; + for (i = depth; i >= 1; i--) + { + if (path[i - 1].ctz.idx_e == 0 && path[i - 1].ctz.pg_e == 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz) && + n->path[i - 1].off == path[i - 1].off) + { + found = true; + } + else if (path[i - 1].ctz.pg_e != 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz)) + { + found = true; + } + else + { + break; + } + } + + if (found) + { + n->path[depth - 1].sz = new_sz; + } + } + + if (depth == 1) + { + MFS_MN(sb).root_sz = new_sz; + goto errout; + } + + memset(buf, 0, sizeof(mfs_t)); + mfs_ser_mfs(new_sz, buf); + + /* This function will be used by mfs_lru_wr itself, but given that if + * there is no change in size, this won't cause an infinite loop, this + * should be fine. + */ + + ret = mfs_lru_wr(sb, path[depth - 2].off + offsetof(struct mfs_dirent_s, + sz), sizeof(mfs_t), path, depth, buf); + if (predict_false(ret < 0)) + { + goto errout; + } + + path[depth - 1].sz = new_sz; + +errout: + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz) + FAR struct mfs_path_s * const path, const mfs_t depth) { struct mfs_node_s *node = NULL; @@ -423,168 +595,212 @@ int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, return OK; } - return lru_nodeflush(sb, path, depth, ctz_sz, node, true); + return lru_nodeflush(sb, path, depth, node, true); } int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t bytes, mfs_t ctz_sz, - FAR struct mfs_path_s * const path, const mfs_t depth) + mfs_t bytes, FAR struct mfs_path_s * const path, + const mfs_t depth) { - return lru_wrtooff(sb, data_off, bytes, ctz_sz, MFS_LRU_DEL, path, depth, - NULL); + return lru_wrtooff(sb, data_off, bytes, MFS_LRU_DEL, path, depth, NULL); } int mfs_lru_wr(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t bytes, mfs_t ctz_sz, FAR struct mfs_path_s * const path, + mfs_t bytes, FAR struct mfs_path_s * const path, const mfs_t depth, FAR const char *buf) { - return lru_wrtooff(sb, data_off, bytes, ctz_sz, MFS_LRU_UPD, path, depth, - buf); + return lru_wrtooff(sb, data_off, bytes, MFS_LRU_UPD, path, depth, buf); +} + +void mfs_lru_init(FAR struct mfs_sb_s * const sb) +{ + list_initialize(&MFS_LRU(sb)); + sb->n_lru = 0; + + finfo("LRU Initialized\n"); } -int mfs_lru_rdfromoff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, +int mfs_lru_rdfromoff(FAR const struct mfs_sb_s * const sb, + const mfs_t data_off, FAR struct mfs_path_s * const path, const mfs_t depth, FAR char *buf, const mfs_t buflen) { - int ret = OK; - mfs_t s; - mfs_t e; - mfs_t end; - mfs_t start; - mfs_t del_b; + /* Requires updated path from the journal. */ + + int ret = OK; + mfs_t upper; + mfs_t lower; + mfs_t rem_sz; + mfs_t upper_og; + mfs_t upper_upd; + mfs_t lower_upd; + FAR char *tmp; + struct mfs_ctz_s ctz; FAR struct mfs_node_s *node = NULL; FAR struct mfs_delta_s *delta = NULL; - finfo("Reading from offset %u, %u bytes", data_off, buflen); - - ret = mfs_ctz_rdfromoff(sb, data_off, path, depth, buf, buflen); - if (predict_false(ret < 0)) - { - goto errout; - } - lru_nodesearch(sb, path, depth, &node); if (node == NULL) { goto errout; } - start = data_off; - end = data_off + buflen; - del_b = 0; + /* Node is NOT supposed to be freed by the caller, it's a reference to + * the actual node in the LRU and freeing it could break the entire LRU. + */ + + tmp = buf; + ctz = node->path[node->depth - 1].ctz; + lower = data_off; + upper_og = lower + buflen; + upper = upper_og; + rem_sz = buflen; - do + while (rem_sz > 0) { + mfs_ctz_rdfromoff(sb, ctz, lower, rem_sz, tmp); + list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) { - if (delta->upd) + if (delta->upd == NULL) { - s = MAX(delta->off, start); - e = MIN(delta->off + delta->n_b, end); + /* Delete */ - if (s >= e) + lower_upd = MAX(lower, delta->off); + upper_upd = MIN(upper, delta->off + delta->n_b); + + if (lower_upd >= upper_upd) { - continue; + /* Outside range */ } + else + { + memmove(tmp + (lower - lower_upd), + tmp + (upper_upd - lower), upper - upper_upd); - memcpy(buf + (s - data_off), delta->upd + (s - delta->off), - e - s); + upper -= (upper_upd - lower_upd); + } } else { - s = MAX(delta->off, start); - e = MIN(delta->off + delta->n_b, end); + /* Update */ - if (s >= end) - { - continue; - } + lower_upd = MAX(lower, delta->off); + upper_upd = MIN(upper, delta->off + delta->n_b); - if (e <= start) + if (lower_upd >= upper_upd) { - del_b += delta->n_b; - s = data_off + delta->n_b; - e = end; - memmove(buf, buf + delta->n_b, - buflen - delta->n_b); - e = data_off + buflen - delta->n_b; + /* Outside range */ } else { - del_b += e - s; - memmove(buf + s, buf + e, buflen - (e - s)); - e = data_off + buflen - (e - s); + memcpy(tmp + (lower_upd - lower), + delta->upd + (lower_upd - delta->off), + upper_upd - lower_upd); } } - - start = s; - end = e; } - start = end; - end = data_off + buflen; + tmp += upper - lower; + rem_sz -= upper - lower; + lower = upper; + upper = upper_og; } - while (start != end); errout: return ret; } -void mfs_lru_init(FAR struct mfs_sb_s * const sb) +int mfs_lru_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth) { - list_initialize(&MFS_LRU(sb)); - sb->n_lru = 0; + int ret = OK; + bool found; + mfs_t i; + FAR struct mfs_node_s *node = NULL; - finfo("LRU Initialized\n"); -} + DEBUGASSERT(depth > 0); -void mfs_lru_updatedsz(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, mfs_t *n_sz) -{ - mfs_t o_sz; - FAR struct mfs_node_s *node = NULL; - FAR struct mfs_delta_s *delta = NULL; - - if (depth == 0) + list_for_every_entry(&MFS_LRU(sb), node, struct mfs_node_s, list) { - /* Master node */ + /* TODO: When a directory is newly created, and still in the LRU, its + * CTZ is (0, 0), and this can match others as well if at same depth, + * so, in these cases, match the parents, and so on up. + */ - o_sz = 0; - } + DEBUGASSERT(node->depth > 0); - if (depth == 1) - { - /* Root node. */ + if (node->depth > depth) + { + continue; + } - o_sz = MFS_MN(sb).root_sz; - } - else - { - o_sz = path[depth - 1].sz; - } + /* We need this loop to specifically check the parents in case these + * entries are all new, and have not been allocated any pages for + * being stored in the flash. Also we know that the root (depth 1) will + * be at least common in their paths. + */ - *n_sz = o_sz; + found = true; + for (i = node->depth; i >= 1 && found; i--) + { + if (path[i - 1].ctz.idx_e == 0 && path[i - 1].ctz.pg_e == 0 && + mfs_ctz_eq(&node->path[i - 1].ctz, &path[i - 1].ctz) && + node->path[i - 1].off == path[i - 1].off) + { + /* OK */ + } + else if (path[i - 1].ctz.pg_e != 0 && + mfs_ctz_eq(&node->path[i - 1].ctz, &path[i - 1].ctz)) + { + /* OK */ + } + else + { + found = false; + } + } - lru_nodesearch(sb, path, depth, &node); - if (node == NULL) - { - finfo("No updates for file size, with depth %u.", depth); - return; + if (found) + { + path[node->depth - 1].sz = node->path[node->depth - 1].sz; + } } - list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) + return ret; +} + +int mfs_lru_updatectz(FAR struct mfs_sb_s * sb, + FAR struct mfs_path_s * const path, const mfs_t depth, + const struct mfs_ctz_s new_ctz) +{ + int ret = OK; + char buf[sizeof(struct mfs_ctz_s)]; + FAR struct mfs_node_s *node = NULL; + + list_for_every_entry(&MFS_LRU(sb), node, struct mfs_node_s, list) { - finfo("depth %u %u %u %p", depth, delta->n_b, delta->off, delta->upd); - if (delta->upd == NULL) + if (node->depth >= depth && + mfs_ctz_eq(&node->path[depth - 1].ctz, &path[depth - 1].ctz) && + node->path[depth - 1].sz == path[depth - 1].sz) { - *n_sz -= MIN((*n_sz) - delta->off, delta->n_b); - } - else - { - *n_sz = MAX(*n_sz, delta->off + delta->n_b); + node->path[depth - 1].ctz = new_ctz; } } - finfo("Updated file size is %u with depth %u.", *n_sz, depth); + memset(buf, 0, sizeof(struct mfs_ctz_s)); + mfs_ser_ctz(&new_ctz, buf); + + ret = mfs_lru_wr(sb, path[depth - 1].off + offsetof(struct mfs_dirent_s, + ctz), sizeof(struct mfs_ctz_s), path, depth, buf); + if (predict_false(ret < 0)) + { + goto errout; + } + + path[depth - 1].ctz = new_ctz; + +errout: + return ret; } diff --git a/fs/mnemofs/mnemofs_master.c b/fs/mnemofs/mnemofs_master.c index 3f94720aa83aa..7f5b0ebacad5e 100644 --- a/fs/mnemofs/mnemofs_master.c +++ b/fs/mnemofs/mnemofs_master.c @@ -186,15 +186,15 @@ static FAR const char *deser_mn(FAR const char * const in, int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk) { - int ret = OK; - mfs_t i = 0; + int ret = OK; + mfs_t i = 0; mfs_t mblk1; mfs_t mblk2; mfs_t jrnl_blk_tmp; - bool found = false; + bool found = false; uint8_t hash; struct mfs_mn_s mn; - const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); + const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); char buftmp[4]; char buf[sz + 1]; @@ -265,14 +265,14 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk) int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk) { - int ret = OK; + int ret = OK; mfs_t pg; mfs_t mblk1; mfs_t mblk2; struct mfs_mn_s mn; - const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); - char buf[sz + 1]; struct timespec ts; + const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); + char buf[sz + 1]; clock_gettime(CLOCK_REALTIME, &ts); diff --git a/fs/mnemofs/mnemofs_rw.c b/fs/mnemofs/mnemofs_rw.c index 4a01e8aec9976..20ef4331ce8d7 100644 --- a/fs/mnemofs/mnemofs_rw.c +++ b/fs/mnemofs/mnemofs_rw.c @@ -85,12 +85,22 @@ int mfs_isbadblk(FAR const struct mfs_sb_s * const sb, mfs_t blk) { + if (predict_false(blk > MFS_NBLKS(sb))) + { + return -EINVAL; + } + return MTD_ISBAD(MFS_MTD(sb), blk); } int mfs_markbadblk(FAR const struct mfs_sb_s * const sb, mfs_t blk) { - return MTD_ISBAD(MFS_MTD(sb), blk); + if (predict_false(blk > MFS_NBLKS(sb))) + { + return -EINVAL; + } + + return MTD_MARKBAD(MFS_MTD(sb), blk); } /* NOTE: These functions do not update the block allocator's state nor do @@ -103,6 +113,11 @@ ssize_t mfs_write_page(FAR const struct mfs_sb_s * const sb, { int ret = OK; + if (predict_false(page > MFS_NPGS(sb) || pgoff >= MFS_PGSZ(sb))) + { + return -EINVAL; + } + mempcpy(MFS_RWBUF(sb) + pgoff, data, datalen); ret = MTD_BWRITE(MFS_MTD(sb), page, 1, MFS_RWBUF(sb)); @@ -123,6 +138,11 @@ ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb, { int ret = OK; + if (predict_false(page > MFS_NPGS(sb) || pgoff >= MFS_PGSZ(sb))) + { + return -EINVAL; + } + ret = MTD_BREAD(MFS_MTD(sb), page, 1, MFS_RWBUF(sb)); if (ret < 0) { @@ -139,11 +159,21 @@ ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb, int mfs_erase_blk(FAR const struct mfs_sb_s * const sb, const off_t blk) { + if (predict_false(blk > MFS_NBLKS(sb))) + { + return -EINVAL; + } + return MTD_ERASE(MFS_MTD(sb), blk, 1); } int mfs_erase_nblks(FAR const struct mfs_sb_s * const sb, const off_t blk, const size_t n) { + if (predict_false(blk + n > MFS_NBLKS(sb))) + { + return -EINVAL; + } + return MTD_ERASE(MFS_MTD(sb), blk, n); } diff --git a/fs/mnemofs/mnemofs_util.c b/fs/mnemofs/mnemofs_util.c index 0815bd352e7af..a9b1efe032ad4 100644 --- a/fs/mnemofs/mnemofs_util.c +++ b/fs/mnemofs/mnemofs_util.c @@ -92,6 +92,8 @@ uint8_t mfs_arrhash(FAR const char *arr, ssize_t len) ssize_t r = len - 1; uint16_t hash = 0; + /* TODO: Change the array checksum to be 16 bit long. */ + while (l <= r) { hash += arr[l] * arr[r] * (l + 1) * (r + 1); @@ -105,6 +107,27 @@ uint8_t mfs_arrhash(FAR const char *arr, ssize_t len) return hash % (1 << 8); } +uint16_t mfs_hash(FAR const char *arr, ssize_t len) +{ + ssize_t l = 0; + ssize_t r = len - 1; + uint32_t hash = 0; + + /* TODO: Change the array checksum to be 16 bit long. */ + + while (l <= r) + { + hash += arr[l] * arr[r] * (l + 1) * (r + 1); + l++; + r--; + hash %= (1 << MFS_HASHSZ); + } + + finfo("Hash calculated for size %ld to be %u.", len, hash); + + return hash; +} + FAR char *mfs_ser_8(const uint8_t n, FAR char * const out) { *out = n; @@ -189,6 +212,28 @@ FAR const char *mfs_deser_ctz(FAR const char * const in, return i; } +FAR char *mfs_ser_path(FAR const struct mfs_path_s * const x, + FAR char * const out) +{ + char *o = out; + + o = mfs_ser_ctz(&x->ctz, o); + o = mfs_ser_mfs(x->off, o); + o = mfs_ser_mfs(x->sz, o); + return o; +} + +FAR const char *mfs_deser_path(FAR const char * const in, + FAR struct mfs_path_s * const x) +{ + const char *i = in; + + i = mfs_deser_ctz(i, &x->ctz); + i = mfs_deser_mfs(i, &x->off); + i = mfs_deser_mfs(i, &x->sz); + return i; +} + FAR char *mfs_ser_timespec(FAR const struct timespec * const x, FAR char * const out) { @@ -225,3 +270,16 @@ mfs_t mfs_set_msb(mfs_t n) { return 31 - mfs_clz(n); } + +bool mfs_ctz_eq(FAR const struct mfs_ctz_s * const a, + FAR const struct mfs_ctz_s * const b) +{ + return a->idx_e == b->idx_e && a->pg_e == b->pg_e; +} + +bool mfs_path_eq(FAR const struct mfs_path_s * const a, + FAR const struct mfs_path_s * const b) +{ + return mfs_ctz_eq(&a->ctz, &b->ctz) && (a->off == b->off) + && (a->sz == b->sz); +} diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c index e4f5e6b2579b5..34f2233630103 100644 --- a/fs/tmpfs/fs_tmpfs.c +++ b/fs/tmpfs/fs_tmpfs.c @@ -1605,7 +1605,15 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, /* Handle attempts to write beyond the end of the file */ - startpos = filep->f_pos; + if ((filep->f_oflags & O_APPEND) != 0) + { + startpos = tfo->tfo_size; + } + else + { + startpos = filep->f_pos; + } + nwritten = buflen; endpos = startpos + buflen; @@ -1625,13 +1633,14 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, if (tfo->tfo_data != NULL) { memcpy(&tfo->tfo_data[startpos], buffer, nwritten); - filep->f_pos += nwritten; } else { DEBUGASSERT(tfo->tfo_size == 0 && nwritten == 0); } + filep->f_pos = endpos; + /* Release the lock on the file */ tmpfs_unlock_file(tfo); diff --git a/include/elf.h b/include/elf.h index fbd8e5391a385..5de67bf2f2210 100644 --- a/include/elf.h +++ b/include/elf.h @@ -233,6 +233,12 @@ #define PF_X 1 /* Execute */ #define PF_W 2 /* Write */ #define PF_R 4 /* Read */ +#define PF_MASKOS 0x0ff00000 /* All bits included in the PF_MASKOS + * mask are reserved for operating system-specific + * semantics. + */ +#define PF_REGISTER 0x00100000 /* Register, need pointer aligned access */ + #define PF_MASKPROC 0xf0000000 /* Unspecified */ /* Figure 5-10: Dynamic Array Tags, d_tag */ diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h index c5610df5972cd..eb928d4c74cf8 100644 --- a/include/nuttx/compiler.h +++ b/include/nuttx/compiler.h @@ -887,7 +887,7 @@ /* Pre-processor */ -# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */ +# undef CONFIG_CPP_HAVE_VARARGS /* No variable argument macros */ /* Intriniscs */ @@ -936,6 +936,8 @@ # define syslog_like(a, b) # define scanf_like(a, b) # define strftime_like(a) +# define object_size(o, t) ((size_t)-1) +# define typeof __typeof__ # define FAR # define NEAR diff --git a/sched/misc/coredump.h b/include/nuttx/coredump.h similarity index 80% rename from sched/misc/coredump.h rename to include/nuttx/coredump.h index 32dc3a6c2c674..8d2cf207a39e9 100644 --- a/sched/misc/coredump.h +++ b/include/nuttx/coredump.h @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/misc/coredump.h + * include/nuttx/coredump.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,19 +18,30 @@ * ****************************************************************************/ -#ifndef __SCHED_MISC_COREDUMP_H -#define __SCHED_MISC_COREDUMP_H +#ifndef __INCLUDE_NUTTX_COREDUMP_H +#define __INCLUDE_NUTTX_COREDUMP_H /**************************************************************************** * Included Files ****************************************************************************/ +#include #include /**************************************************************************** * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: coredump_set_memory_region + * + * Description: + * Set do coredump memory region. + * + ****************************************************************************/ + +int coredump_set_memory_region(FAR struct memory_region_s *region); + /**************************************************************************** * Name: coredump_initialize * @@ -55,4 +66,4 @@ int coredump_initialize(void); void coredump_dump(pid_t pid); -#endif /* __SCHED_MISC_COREDUMP_H */ +#endif /* __INCLUDE_NUTTX_COREDUMP_H */ diff --git a/include/nuttx/i2c/i2c_master.h b/include/nuttx/i2c/i2c_master.h index 39ba782f8bba5..da74c9faa299d 100644 --- a/include/nuttx/i2c/i2c_master.h +++ b/include/nuttx/i2c/i2c_master.h @@ -171,6 +171,38 @@ # define I2C_RESET(d) ((d)->ops->reset(d)) #endif +/**************************************************************************** + * Name: I2C_SETUP + * + * Description: + * I2c master initialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2C_SETUP(d) ((d)->ops->setup(d)) + +/**************************************************************************** + * Name: I2C_SHUTDOWN + * + * Description: + * I2c master uninitialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2C_SHUTDOWN(d) ((d)->ops->shutdown(d)) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -186,6 +218,8 @@ struct i2c_ops_s #ifdef CONFIG_I2C_RESET CODE int (*reset)(FAR struct i2c_master_s *dev); #endif + CODE int (*setup)(FAR struct i2c_master_s *dev); + CODE int (*shutdown)(FAR struct i2c_master_s *dev); }; /* This structure contains the full state of I2C as needed for a specific diff --git a/include/nuttx/i2c/i2c_slave.h b/include/nuttx/i2c/i2c_slave.h index ef29ab6ceda60..2bbaccf618508 100644 --- a/include/nuttx/i2c/i2c_slave.h +++ b/include/nuttx/i2c/i2c_slave.h @@ -170,13 +170,52 @@ #define I2CS_REGISTERCALLBACK(d,c,a) ((d)->ops->registercallback(d,c,a)) +/**************************************************************************** + * Name: I2CS_SETUP + * + * Description: + * I2c slave initialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2CS_SETUP(d) ((d)->ops->setup(d)) + +/**************************************************************************** + * Name: I2CS_SHUTDOWN + * + * Description: + * I2c slave uninitialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2CS_SHUTDOWN(d) ((d)->ops->shutdown(d)) + /**************************************************************************** * Public Types ****************************************************************************/ +typedef enum i2c_slave_complete_e +{ + I2CS_RX_COMPLETE = 0, + I2CS_TX_COMPLETE +} i2c_slave_complete_t; + /* The callback function */ -typedef int (i2c_slave_callback_t)(void *arg, size_t rx_len); +typedef int (i2c_slave_callback_t)(FAR void *arg, i2c_slave_complete_t state, + size_t len); /* The I2C vtable */ @@ -198,6 +237,8 @@ struct i2c_slaveops_s int (*registercallback)(FAR struct i2c_slave_s *dev, i2c_slave_callback_t *callback, FAR void *arg); + int (*setup)(FAR struct i2c_slave_s *dev); + int (*shutdown)(FAR struct i2c_slave_s *dev); }; /* I2C private data. This structure only defines the initial fields of the @@ -223,6 +264,33 @@ extern "C" #define EXTERN extern #endif +#ifdef CONFIG_I2C_SLAVE_DRIVER + +/**************************************************************************** + * Name: i2c_slave_register + * + * Description: + * Register the I2C Slave character device driver as 'devpath'. + * + * Input Parameters: + * dev - An instance of the I2C Slave interface to use to communicate + * with the I2C Slave device + * bus - The I2C Slave bus number. This will be used as the I2C device + * minor number. The I2C Slave character device will be + * registered as /dev/i2cslvN where N is the minor number + * addr - I2C Slave address + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, + int nbit); + +#endif + #undef EXTERN #if defined(__cplusplus) } diff --git a/include/nuttx/input/touchscreen.h b/include/nuttx/input/touchscreen.h index 7a191bb943d28..34801e11deb8e 100644 --- a/include/nuttx/input/touchscreen.h +++ b/include/nuttx/input/touchscreen.h @@ -89,8 +89,12 @@ * int Y threshold value */ +#define TSIOC_GRAB _TSIOC(0x000e) /* arg: Pointer to + * int for enable grab + */ + #define TSC_FIRST 0x0001 /* First common command */ -#define TSC_NCMDS 13 /* Thirteen common commands */ +#define TSC_NCMDS 14 /* Fourteen common commands */ /* Backward compatible IOCTL */ diff --git a/include/nuttx/mtd/nand_ram.h b/include/nuttx/mtd/nand_ram.h index 5229882e42b83..c3483ed06ac5c 100644 --- a/include/nuttx/mtd/nand_ram.h +++ b/include/nuttx/mtd/nand_ram.h @@ -43,14 +43,14 @@ #define NAND_RAM_SIZE NAND_RAM_MB(CONFIG_MTD_NAND_RAM_SIZE) -#define NAND_RAM_LOG_PAGES_PER_BLOCK ((uint32_t) 7) -#define NAND_RAM_PAGE_SIZE ((uint32_t) (1 << 9)) /* 512 B */ -#define NAND_RAM_SPARE_SIZE ((uint32_t) (1 << 4)) /* 16 B */ +#define NAND_RAM_LOG_PAGES_PER_BLOCK ((uint32_t) 4) +#define NAND_RAM_PAGE_SIZE ((uint32_t) (1 << 7)) +#define NAND_RAM_SPARE_SIZE ((uint32_t) (1 << 3)) +#define NAND_RAM_BLOCK_SIZE ((uint32_t) ((1 << NAND_RAM_LOG_PAGES_PER_BLOCK) * NAND_RAM_PAGE_SIZE)) #define NAND_RAM_N_PAGES ((uint32_t) NAND_RAM_SIZE / NAND_RAM_PAGE_SIZE) #define NAND_RAM_TOTAL_PAGE_SIZE ((uint32_t) (NAND_RAM_PAGE_SIZE + NAND_RAM_SPARE_SIZE)) -#define NAND_RAM_PAGES_PER_BLOCK ((uint32_t) (NAND_RAM_BLOCK_SIZE / NAND_RAM_PAGE_SIZE)) -#define NAND_RAM_N_BLOCKS ((uint32_t) (NAND_RAM_N_PAGES / NAND_RAM_PAGES_PER_BLOCK)) -#define NAND_RAM_BLOCK_SIZE ((uint32_t) ((1 << NAND_RAM_LOG_PAGES_PER_BLOCK) * NAND_RAM_PAGE_SIZE)) +#define NAND_RAM_PAGES_PER_BLOCK ((uint32_t) (1 << (NAND_RAM_LOG_PAGES_PER_BLOCK))) +#define NAND_RAM_N_BLOCKS ((uint32_t) (NAND_RAM_SIZE / (NAND_RAM_PAGES_PER_BLOCK * NAND_RAM_PAGE_SIZE))) #define NAND_RAM_PAGE_WRITTEN 0 #define NAND_RAM_PAGE_FREE 1 diff --git a/include/nuttx/net/netfilter/ip6_tables.h b/include/nuttx/net/netfilter/ip6_tables.h index 018132a09c026..8f24797ec74e6 100644 --- a/include/nuttx/net/netfilter/ip6_tables.h +++ b/include/nuttx/net/netfilter/ip6_tables.h @@ -296,7 +296,7 @@ struct ip6t_icmp static inline FAR struct xt_entry_target * ip6t_get_target(FAR struct ip6t_entry *e) { - return (FAR void *)e + e->target_offset; + return (FAR char *)e + e->target_offset; } #endif /* __INCLUDE_NUTTX_NET_NETFILTER_IP6_TABLES_H */ diff --git a/include/nuttx/spinlock.h b/include/nuttx/spinlock.h index 1d915a6314a51..ebb5d91328c59 100644 --- a/include/nuttx/spinlock.h +++ b/include/nuttx/spinlock.h @@ -626,6 +626,81 @@ irqstate_t spin_lock_irqsave(FAR volatile spinlock_t *lock) # define spin_lock_irqsave(l) ((void)(l), up_irq_save()) #endif +/**************************************************************************** + * Name: spin_trylock_irqsave_wo_note + * + * Description: + * Try once to lock the spinlock. Do not wait if the spinlock is already + * locked. + * + * This implementation is the same as the above spin_trylock() except that + * it does not perform instrumentation logic. + * + * Input Parameters: + * lock - A reference to the spinlock object to lock. + * flags - flag of interrupts status + * + * Returned Value: + * SP_LOCKED - Failure, the spinlock was already locked + * SP_UNLOCKED - Success, the spinlock was successfully locked + * + * Assumptions: + * Not running at the interrupt level. + * + ****************************************************************************/ + +#ifdef CONFIG_SPINLOCK +# define spin_trylock_irqsave_wo_note(l, f) \ +({ \ + f = up_irq_save(); \ + spin_trylock_wo_note(l) ? \ + true : ({ up_irq_restore(f); false; }); \ +}) +#else +# define spin_trylock_irqsave_wo_note(l, f) \ +({ \ + (void)(l); \ + f = up_irq_save(); \ + true; \ +}) +#endif /* CONFIG_SPINLOCK */ + +/**************************************************************************** + * Name: spin_trylock_irqsave + * + * Description: + * Try once to lock the spinlock. Do not wait if the spinlock is already + * locked. + * + * Input Parameters: + * lock - A reference to the spinlock object to lock. + * flags - flag of interrupts status + * + * Returned Value: + * SP_LOCKED - Failure, the spinlock was already locked + * SP_UNLOCKED - Success, the spinlock was successfully locked + * + * Assumptions: + * Not running at the interrupt level. + * + ****************************************************************************/ + +#ifdef CONFIG_SPINLOCK +# define spin_trylock_irqsave(l, f) \ +({ \ + f = up_irq_save(); \ + spin_trylock(l) ? \ + true : ({ up_irq_restore(f); false; }); \ +}) +#else +# define spin_trylock_irqsave(l, f) \ +({ \ + (void)(l); \ + f = up_irq_save(); \ + true; \ +}) +#endif /* CONFIG_SPINLOCK */ + /**************************************************************************** * Name: spin_unlock_irqrestore_wo_note * diff --git a/include/sys/types.h b/include/sys/types.h index a87827b5f199b..a316397d89be6 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -192,14 +192,14 @@ typedef _wchar_t wchar_t; * An integral type capable of storing any valid value of wchar_t, or WEOF. */ -typedef int wint_t; +typedef _wint_t wint_t; /* wctype_t * A scalar type of a data object that can hold values which represent * locale-specific character classification. */ -typedef int wctype_t; +typedef _wctype_t wctype_t; #if defined(CONFIG_FS_LARGEFILE) /* Large file versions */ diff --git a/libs/libc/machine/arm/armv7-a/CMakeLists.txt b/libs/libc/machine/arm/armv7-a/CMakeLists.txt index 05bd859ebee7b..7744719bb994f 100644 --- a/libs/libc/machine/arm/armv7-a/CMakeLists.txt +++ b/libs/libc/machine/arm/armv7-a/CMakeLists.txt @@ -18,8 +18,6 @@ # # ############################################################################## -set(SRCS arch_elf.c) - if(CONFIG_ARCH_TOOLCHAIN_GNU) set(ARCH_TOOLCHAIN_DIR gnu) endif() @@ -48,4 +46,8 @@ if(CONFIG_ARMV7A_STRLEN) list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() +if(CONFIG_LIBC_ARCH_ELF) + list(APPEND SRCS arch_elf.c) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/machine/arm/armv7-m/CMakeLists.txt b/libs/libc/machine/arm/armv7-m/CMakeLists.txt index e5395a486ea4a..10f7b2b9af231 100644 --- a/libs/libc/machine/arm/armv7-m/CMakeLists.txt +++ b/libs/libc/machine/arm/armv7-m/CMakeLists.txt @@ -20,28 +20,36 @@ set(SRCS) +if(CONFIG_ARCH_TOOLCHAIN_GNU) + set(ARCH_TOOLCHAIN_DIR gnu) +endif() + +if(CONFIG_ARMV7M_MEMCHR) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memchr.S) +endif() + if(CONFIG_ARMV7M_MEMCPY) - list(APPEND SRCS gnu/arch_memcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memcpy.S) endif() if(CONFIG_ARMV7M_MEMSET) - list(APPEND SRCS arch_memset.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memset.S) endif() if(CONFIG_ARMV7M_MEMMOVE) - list(APPEND SRCS arch_memmove.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memmove.S) endif() if(CONFIG_ARMV7M_STRCMP) - list(APPEND SRCS arch_strcmp.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcmp.S) endif() if(CONFIG_ARMV7M_STRCPY) - list(APPEND SRCS arch_strcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcpy.S) endif() if(CONFIG_ARMV7M_STRLEN) - list(APPEND SRCS arch_strlen.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() if(CONFIG_LIBC_ARCH_ELF) diff --git a/libs/libc/machine/arm/armv7-r/CMakeLists.txt b/libs/libc/machine/arm/armv7-r/CMakeLists.txt index 62ec1bed478f4..dbbedfb4da9d4 100644 --- a/libs/libc/machine/arm/armv7-r/CMakeLists.txt +++ b/libs/libc/machine/arm/armv7-r/CMakeLists.txt @@ -18,10 +18,38 @@ # # ############################################################################## +set(SRCS) + +if(CONFIG_ARCH_TOOLCHAIN_GNU) + set(ARCH_TOOLCHAIN_DIR gnu) +endif() + +if(CONFIG_ARMV7R_MEMCHR) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memchr.S) +endif() + if(CONFIG_ARMV7R_MEMCPY) - target_sources(c PRIVATE gnu/arch_memcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memcpy.S) +endif() + +if(CONFIG_ARMV7R_MEMSET) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memset.S) +endif() + +if(CONFIG_ARMV7R_MEMMOVE) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memmove.S) +endif() + +if(CONFIG_ARMV7R_STRCMP) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcmp.S) +endif() + +if(CONFIG_ARMV7R_STRLEN) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() if(CONFIG_LIBC_ARCH_ELF) - target_sources(c PRIVATE arch_elf.c) + list(APPEND SRCS arch_elf.c) endif() + +target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/machine/arm/armv8-m/CMakeLists.txt b/libs/libc/machine/arm/armv8-m/CMakeLists.txt index 71cc3a774df7e..809f82fe6e125 100644 --- a/libs/libc/machine/arm/armv8-m/CMakeLists.txt +++ b/libs/libc/machine/arm/armv8-m/CMakeLists.txt @@ -20,36 +20,40 @@ set(SRCS) +if(CONFIG_ARCH_TOOLCHAIN_GNU) + set(ARCH_TOOLCHAIN_DIR gnu) +endif() + if(CONFIG_LIBC_ARCH_ELF) list(APPEND SRCS arch_elf.c) endif() if(CONFIG_ARMV8M_MEMCHR) - list(APPEND SRCS arch_memchr.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memchr.S) endif() if(CONFIG_ARMV8M_MEMCPY) - list(APPEND SRCS arch_memcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memcpy.S) endif() if(CONFIG_ARMV8M_MEMSET) - list(APPEND SRCS arch_memset.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memset.S) endif() if(CONFIG_ARMV8M_MEMMOVE) - list(APPEND SRCS arch_memmove.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memmove.S) endif() if(CONFIG_ARMV8M_STRCMP) - list(APPEND SRCS arch_strcmp.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcmp.S) endif() if(CONFIG_ARMV8M_STRCPY) - list(APPEND SRCS arch_strcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcpy.S) endif() if(CONFIG_ARMV8M_STRLEN) - list(APPEND SRCS arch_strlen.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/machine/arm/gnu/arch_setjmp.S b/libs/libc/machine/arm/gnu/arch_setjmp.S index cae0f259fe6b0..77a26adfdd8fa 100644 --- a/libs/libc/machine/arm/gnu/arch_setjmp.S +++ b/libs/libc/machine/arm/gnu/arch_setjmp.S @@ -31,7 +31,9 @@ .globl setjmp .globl longjmp +#ifndef __ghs__ .syntax unified +#endif .file "setjmp.S" /**************************************************************************** @@ -59,7 +61,12 @@ * ****************************************************************************/ +#ifndef __ghs__ .type setjmp, function +#else + .type setjmp, $function +#endif + setjmp: /* Store callee-saved Core registers */ @@ -121,7 +128,11 @@ setjmp: * ****************************************************************************/ +#ifndef __ghs__ .type longjmp, function +#else + .type longjmp, $function +#endif longjmp: /* Load callee-saved Core registers */ diff --git a/libs/libc/misc/CMakeLists.txt b/libs/libc/misc/CMakeLists.txt index d9ae54b35f37f..3beabec7f1ddc 100644 --- a/libs/libc/misc/CMakeLists.txt +++ b/libs/libc/misc/CMakeLists.txt @@ -112,4 +112,12 @@ if(CONFIG_FDCHECK) list(APPEND SRCS lib_fdcheck.c) endif() +if(NOT CONFIG_LIBC_UNAME_DISABLE_TIMESTAMP) + add_custom_target( + always_rebuild_lib_utsname + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_SOURCE_DIR}/lib_utsname.c) + + add_dependencies(c always_rebuild_lib_utsname) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index c3d19570f7f38..c5a1bda0087b3 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -80,7 +80,7 @@ endif # add lib_utsname.o to phony target for force rebuild #if !defined(CONFIG_LIBC_UNAME_DISABLE_TIMESTAMP) -.PHONY: lib_utsname$(OBJEXT) +.PHONY: bin$(DELIM)lib_utsname$(OBJEXT) kbin$(DELIM)lib_utsname$(OBJEXT) #endif # Add the misc directory to the build diff --git a/libs/libc/modlib/modlib_globals.S b/libs/libc/modlib/modlib_globals.S index bdc8912271448..b65edfb51a461 100644 --- a/libs/libc/modlib/modlib_globals.S +++ b/libs/libc/modlib/modlib_globals.S @@ -16,7 +16,11 @@ .type SYMBOL(\ep), "object" .endm .macro SIZE ep +# if defined(__ghs__) + .size SYMBOL(ep), . - SYMBOL(ep) +# else .size SYMBOL(\ep), . - SYMBOL(\ep) +# endif .endm #else # define SYMBOL(s) _##s diff --git a/libs/libc/string/CMakeLists.txt b/libs/libc/string/CMakeLists.txt index aa25dc5ad6889..c893384de296d 100644 --- a/libs/libc/string/CMakeLists.txt +++ b/libs/libc/string/CMakeLists.txt @@ -57,6 +57,7 @@ set(SRCS lib_strsep.c lib_strerrorr.c lib_explicit_bzero.c + lib_bzero.c lib_strsignal.c lib_timingsafe_bcmp.c lib_index.c diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index b8a4843abd724..8e0aebc10eb80 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -221,7 +221,7 @@ static inline void kasan_check_report(FAR const void *addr, size_t size, { if (kasan_is_poisoned(addr, size)) { - kasan_report(addr, size, false, return_address); + kasan_report(addr, size, is_write, return_address); } } diff --git a/net/local/local_conn.c b/net/local/local_conn.c index 55986393c5a1c..55e82899ff6ba 100644 --- a/net/local/local_conn.c +++ b/net/local/local_conn.c @@ -317,7 +317,7 @@ void local_free(FAR struct local_conn_s *conn) void local_addref(FAR struct local_conn_s *conn) { - DEBUGASSERT(conn->lc_crefs >= 0 && conn->lc_crefs < 255); + DEBUGASSERT(conn->lc_crefs < 255); conn->lc_crefs++; } diff --git a/sched/init/nx_bringup.c b/sched/init/nx_bringup.c index 152dcc8ab236e..1affea836e693 100644 --- a/sched/init/nx_bringup.c +++ b/sched/init/nx_bringup.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,6 @@ #include "sched/sched.h" #include "wqueue/wqueue.h" #include "init/init.h" -#include "misc/coredump.h" #ifdef CONFIG_ETC_ROMFS # include diff --git a/sched/misc/assert.c b/sched/misc/assert.c index fa9b8c8916577..2500b0c2bb4b8 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,6 @@ #include "irq/irq.h" #include "sched/sched.h" #include "group/group.h" -#include "misc/coredump.h" /**************************************************************************** * Pre-processor Definitions diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index fcf1a8ca16c87..c8c4f920db871 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -23,11 +23,10 @@ ****************************************************************************/ #include +#include #include #include -#include "misc/coredump.h" - /**************************************************************************** * Private Data ****************************************************************************/ @@ -115,7 +114,7 @@ static void coredump_dump_blkdev(pid_t pid) if (g_blockstream.inode == NULL) { - _alert("Coredump Device Not Found\n"); + _alert("Coredump device not found\n"); return; } @@ -123,14 +122,15 @@ static void coredump_dump_blkdev(pid_t pid) g_blockinfo, g_blockstream.geo.geo_nsectors - 1, 1); if (ret < 0) { - _alert("Coredump Device Read Fail\n"); + _alert("Coredump information read fail\n"); return; } info = (FAR struct coredump_info_s *)g_blockinfo; if (info->magic == COREDUMP_MAGIC) { - _alert("Coredump Device Already Used\n"); + _alert("Coredump exists in %s, skip\n", + CONFIG_BOARD_COREDUMP_BLKDEV_PATH); return; } @@ -143,7 +143,7 @@ static void coredump_dump_blkdev(pid_t pid) ret = core_dump(g_regions, stream, pid); if (ret < 0) { - _alert("Coredump Fail\n"); + _alert("Coredump fail\n"); return; } @@ -151,11 +151,35 @@ static void coredump_dump_blkdev(pid_t pid) info->size = g_blockstream.common.nput; info->time = time(NULL); uname(&info->name); - g_blockstream.inode->u.i_bops->write(g_blockstream.inode, + ret = g_blockstream.inode->u.i_bops->write(g_blockstream.inode, (FAR void *)info, g_blockstream.geo.geo_nsectors - 1, 1); + if (ret < 0) + { + _alert("Coredump information write fail\n"); + return; + } + + _alert("Finish coredump, write %d bytes to %s\n", + info->size, CONFIG_BOARD_COREDUMP_BLKDEV_PATH); } #endif +/**************************************************************************** + * Name: coredump_set_memory_region + * + * Description: + * Set do coredump memory region. + * + ****************************************************************************/ + +int coredump_set_memory_region(FAR struct memory_region_s *region) +{ + /* Not free g_regions, because allow call this fun when crash */ + + g_regions = region; + return 0; +} + /**************************************************************************** * Name: coredump_initialize * @@ -171,10 +195,11 @@ int coredump_initialize(void) if (CONFIG_BOARD_MEMORY_RANGE[0] != '\0') { - g_regions = alloc_memory_region(CONFIG_BOARD_MEMORY_RANGE); + coredump_set_memory_region( + alloc_memory_region(CONFIG_BOARD_MEMORY_RANGE)); if (g_regions == NULL) { - _alert("Memory Region Alloc Fail\n"); + _alert("Coredump memory region alloc fail\n"); return -ENOMEM; } } @@ -184,7 +209,7 @@ int coredump_initialize(void) CONFIG_BOARD_COREDUMP_BLKDEV_PATH); if (ret < 0) { - _alert("%s Coredump Device Not Found\n", + _alert("%s Coredump device not found\n", CONFIG_BOARD_COREDUMP_BLKDEV_PATH); free_memory_region(g_regions); g_regions = NULL; @@ -194,7 +219,7 @@ int coredump_initialize(void) g_blockinfo = kmm_malloc(g_blockstream.geo.geo_sectorsize); if (g_blockinfo == NULL) { - _alert("Coredump Device Memory Alloc Fail\n"); + _alert("Coredump device memory alloc fail\n"); free_memory_region(g_regions); g_regions = NULL; lib_blkoutstream_close(&g_blockstream); diff --git a/sched/sched/sched_get_tls.c b/sched/sched/sched_get_tls.c index 63517429ed3a7..02b64e61e8bb0 100644 --- a/sched/sched/sched_get_tls.c +++ b/sched/sched/sched_get_tls.c @@ -73,5 +73,6 @@ FAR char **nxsched_get_stackargs(FAR struct tcb_s *tcb) { /* The args data follows the TLS data */ - return (FAR char**)(tcb->stack_alloc_ptr + nxsched_get_tls(tcb)->tl_size); + return (FAR char**)((FAR char *)tcb->stack_alloc_ptr + + nxsched_get_tls(tcb)->tl_size); } diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index 1b7985deebd29..a831dd17a47c8 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -250,7 +250,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, irqstate_t flags; sclock_t waitticks; bool switch_needed; - siginfo_t sinfo; + siginfo_t unbinfo; int ret; DEBUGASSERT(set != NULL); @@ -318,7 +318,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, } #endif - rtcb->sigunbinfo = (info == NULL) ? &sinfo : info; + rtcb->sigunbinfo = (info == NULL) ? &unbinfo : info; /* Check if we should wait for the timeout */ diff --git a/sched/tls/tls_initinfo.c b/sched/tls/tls_initinfo.c index 67792004e44a0..306f00bbc35f2 100644 --- a/sched/tls/tls_initinfo.c +++ b/sched/tls/tls_initinfo.c @@ -65,7 +65,8 @@ int tls_init_info(FAR struct tcb_s *tcb) /* Derive tl_size w/o arch knowledge */ - info->tl_size = tcb->stack_base_ptr - tcb->stack_alloc_ptr; + info->tl_size = + (FAR char *)tcb->stack_base_ptr - (FAR char *)tcb->stack_alloc_ptr; /* Attach per-task info in group to TLS */ diff --git a/sched/wqueue/kwork_thread.c b/sched/wqueue/kwork_thread.c index a0a9ea540622b..ef3be25b2f74e 100644 --- a/sched/wqueue/kwork_thread.c +++ b/sched/wqueue/kwork_thread.c @@ -136,9 +136,9 @@ static int work_thread(int argc, FAR char *argv[]) /* Get the handle from argv */ wqueue = (FAR struct kwork_wqueue_s *) - ((uintptr_t)strtoul(argv[1], NULL, 0)); + ((uintptr_t)strtoul(argv[1], NULL, 16)); kworker = (FAR struct kworker_s *) - ((uintptr_t)strtoul(argv[2], NULL, 0)); + ((uintptr_t)strtoul(argv[2], NULL, 16)); flags = enter_critical_section(); diff --git a/tools/ci/docker/linux/Dockerfile b/tools/ci/docker/linux/Dockerfile index 78b43ca5c09fd..845f9bc18b70c 100644 --- a/tools/ci/docker/linux/Dockerfile +++ b/tools/ci/docker/linux/Dockerfile @@ -66,7 +66,8 @@ ENV RUSTUP_HOME=$RUST_HOME/rustup RUN mkdir -p $CARGO_HOME \ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ && $CARGO_HOME/bin/rustup target add thumbv6m-none-eabi \ - && $CARGO_HOME/bin/rustup target add thumbv7m-none-eabi + && $CARGO_HOME/bin/rustup target add thumbv7m-none-eabi \ + && $CARGO_HOME/bin/rustup target add riscv64gc-unknown-none-elf RUN mkdir /tools/gn -p \ && cd /tools/gn \ diff --git a/tools/ci/platforms/msys2.sh b/tools/ci/platforms/msys2.sh index f5230e778c368..687b81cff4c8d 100755 --- a/tools/ci/platforms/msys2.sh +++ b/tools/ci/platforms/msys2.sh @@ -181,6 +181,7 @@ rust() { # Install targets supported from NuttX "$CARGO_HOME"/bin/rustup target add thumbv6m-none-eabi "$CARGO_HOME"/bin/rustup target add thumbv7m-none-eabi + "$CARGO_HOME"/bin/rustup target add riscv64gc-unknown-none-elf rm rustup-init.exe fi command rustc --version diff --git a/tools/ci/platforms/ubuntu.sh b/tools/ci/platforms/ubuntu.sh index e545b4f5aba2b..fdfaaa9bf25cc 100755 --- a/tools/ci/platforms/ubuntu.sh +++ b/tools/ci/platforms/ubuntu.sh @@ -230,6 +230,7 @@ rust() { # Install targets supported from NuttX rustup target add thumbv6m-none-eabi rustup target add thumbv7m-none-eabi + rustup target add riscv64gc-unknown-none-elf fi command rustc --version