├── .devcontainer └── Dockerfile ├── .gitignore ├── LICENSE ├── README.md ├── config.nims ├── nephyr.nimble ├── nims.cfg ├── src ├── .gitignore ├── nephyr.nim └── nephyr │ ├── board_fixes.nim │ ├── build_utils │ └── tasks.nim │ ├── core │ ├── zchannel.nim │ └── zfifo.nim │ ├── devices.nim │ ├── drivers │ ├── Pins.nim │ ├── device.nim │ ├── gpio.nim │ ├── i2c.nim │ ├── nvs.nim │ └── spi.nim │ ├── extras │ ├── .gitignore │ └── nvsConfigObj.nim │ ├── general.nim │ ├── logs.nim │ ├── nets.nim │ ├── randoms.nim │ ├── times.nim │ ├── utils.nim │ ├── zconsts.nim │ └── zephyr │ ├── drivers │ ├── zadc.nim │ ├── zflash.nim │ ├── zflash_img.nim │ ├── zgpio.nim │ ├── zi2c.nim │ ├── znvs.nim │ └── zspi.nim │ ├── dt_bindings │ ├── dt_gpio.nim │ └── dt_spi.nim │ ├── kernel │ ├── zk_extras.nim │ ├── zk_fatal.nim │ ├── zk_fifo.nim │ ├── zk_heap.nim │ ├── zk_locks.nim │ ├── zk_memslab.nim │ ├── zk_msgqueue.nim │ ├── zk_pipe.nim │ ├── zk_poll.nim │ ├── zk_queue.nim │ ├── zk_sem.nim │ ├── zk_stack.nim │ ├── zk_time.nim │ └── zk_work.nim │ ├── net │ ├── zipv6.nim │ ├── znet_config.nim │ ├── znet_core.nim │ ├── znet_if.nim │ ├── znet_if_impl.nim │ ├── znet_ip.nim │ ├── znet_l2.nim │ ├── znet_linkaddr.nim │ ├── znet_mgmt.nim │ └── znet_timeout.nim │ ├── sys │ ├── zdma.nim │ └── zsys_heap.nim │ ├── wrapper_utils.nim │ ├── zatomic.nim │ ├── zcmtoken.nim │ ├── zconfs.nim │ ├── zdevice.nim │ ├── zdevicetree.nim │ ├── zkernel.nim │ ├── zkernel_fixes.nim │ ├── zmcuboot.nim │ ├── zsys_clock.nim │ ├── zthread.nim │ └── ztime_units.nim ├── testresults └── pattern.json ├── tests ├── .gitignore ├── c_headers │ ├── devicetree_dma.h │ ├── dma.h │ ├── example_mcast.nim │ ├── gpio.h │ ├── gpio.nim │ ├── kernel.h │ ├── kernel_structs.nim │ ├── net_core.h │ ├── net_if.h │ ├── net_ip.h │ ├── net_ip.nim │ ├── net_l2.h │ ├── net_linkaddr.h │ ├── net_timeout.h │ ├── sys_clock.h │ ├── sys_heap.h │ └── thread.h ├── config.nims ├── drivers │ ├── config.nims │ ├── tgeneral.nim │ ├── tgpio.nim │ ├── ti2c.nim │ ├── tspi.nim │ └── tspi_c.nim ├── unit_tests │ ├── .gitignore │ ├── config.nims │ ├── nvs_mock.nim │ └── t_nvs_cfg_obj.nim └── zephyr_c │ ├── config.nims │ └── tkernel.nim └── utils └── rpc ├── .gitignore ├── Makefile ├── README.md ├── nim.cfg ├── rpc_cli.nim └── rpc_server_example.nim /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG FROM_TAG 2 | ARG CI_GIT_NI_TOKEN 3 | 4 | FROM zephyrprojectrtos/ci:${FROM_TAG:-latest} 5 | 6 | RUN apt-get -y update \ 7 | && apt-get -y upgrade \ 8 | && apt-get install --no-install-recommends -y \ 9 | python-xdg software-properties-common \ 10 | vim libpython3.8-dev \ 11 | makeself p7zip-full tree curl \ 12 | ca-certificates bash-completion \ 13 | python3-dev python3-pip python3-tk python3-wheel \ 14 | libusb-1.0-0-dev libusb-dev \ 15 | socat \ 16 | ssh \ 17 | tio \ 18 | wget \ 19 | xz-utils \ 20 | udev \ 21 | debhelper \ 22 | cmake \ 23 | iputils-ping \ 24 | netcat \ 25 | kmod \ 26 | && rm -rf /var/lib/apt/lists/* 27 | 28 | RUN wget --post-data "accept_license_agreement=accepted" \ 29 | -O /opt/JLink_Linux_x86_64.deb \ 30 | https://www.segger.com/downloads/jlink/JLink_Linux_V758c_x86_64.deb \ 31 | && dpkg -i /opt/JLink_Linux_x86_64.deb \ 32 | && rm /opt/JLink_Linux_x86_64.deb 33 | 34 | RUN wget https://github.com/stlink-org/stlink/releases/download/v1.7.0/stlink_1.7.0-1_amd64.deb \ 35 | -O /opt/stlink_amd64.deb \ 36 | && mkdir -p /lib/modules/`uname -r` \ 37 | && dpkg -i /opt/stlink_amd64.deb \ 38 | && rm /opt/stlink_amd64.deb 39 | 40 | # Install python packages to allow upload to aws S3 41 | RUN mkdir -p /home/user/.bash_completion.d 42 | RUN chown -R user:user /home/user 43 | RUN echo 'export PATH=$HOME/.nimble/bin:$HOME/Nim/bin:$PATH' >> /etc/profile.d/nimble.sh 44 | 45 | USER user 46 | 47 | RUN pip3 install setuptools awscli \ 48 | && python3 -mpip install -U pyocd 49 | 50 | ENV ZEPHYR_HOME=/home/user/zephyrproject 51 | RUN cd /home/user/ \ 52 | && west init -m https://github.com/EmbeddedNim/zephyr --mr nephyr-v2.7-branch-patched ${ZEPHYR_HOME} \ 53 | && cd ${ZEPHYR_HOME} \ 54 | && west update \ 55 | && cd $HOME 56 | 57 | RUN cd ${ZEPHYR_HOME}/tools/net-tools/ \ 58 | && make 59 | 60 | # RUN cd $HOME/ \ 61 | # && wget https://nim-lang.org/choosenim/init.sh \ 62 | # && sh init.sh -y \ 63 | # && ~/.nimble/bin/choosenim -y 'devel' --latest \ 64 | # && cd ~/.choosenim/toolchains/nim-#devel \ 65 | # && git remote add fork https://github.com/EmbeddedNim/Nim.git \ 66 | # && git fetch fork \ 67 | # && git reset --hard \ 68 | # && git checkout -t fork/devel-patched \ 69 | # && ./build_all.sh 70 | 71 | RUN cd $HOME/ \ 72 | && git clone --branch devel-patched --depth=1 https://github.com/EmbeddedNim/Nim.git \ 73 | && cd Nim \ 74 | && ./build_all.sh \ 75 | && echo 'export PATH=$HOME/Nim/bin:$PATH' >> ~/.bashrc 76 | 77 | RUN mkdir ${HOME}/app/ \ 78 | && touch ${HOME}/.bashrc \ 79 | && echo 'alias gs="git status"' >> ${HOME}/.bashrc \ 80 | && echo 'alias gc="git commit"' >> ${HOME}/.bashrc \ 81 | && echo 'alias gp="git push"' >> ${HOME}/.bashrc \ 82 | && echo 'alias gu="git pull"' >> ${HOME}/.bashrc \ 83 | && echo 'alias gf="git diff"' >> ${HOME}/.bashrc 84 | 85 | RUN . /etc/profile.d/nimble.sh \ 86 | && echo "2022-04-12-r1" \ 87 | && cd ${HOME} \ 88 | && git clone --branch main 'https://github.com/EmbeddedNim/nephyr.git' && cd nephyr/ && nimble develop -y \ 89 | && cd ${HOME} \ 90 | && git clone --branch main 'https://github.com/EmbeddedNim/mcu_utils.git' && cd mcu_utils/ && nimble develop -y \ 91 | && cd ${HOME} \ 92 | && git clone --branch devel 'https://github.com/EmbeddedNim/fastrpc.git' && cd fastrpc/ && nimble develop -y \ 93 | && cd ${HOME} \ 94 | && git clone --branch main "https://github.com/EmbeddedNim/devicedrivers.git" && cd devicedrivers/ && nimble develop -y 95 | 96 | ADD update-all-deps.sh /home/user/update-all-deps.sh 97 | 98 | WORKDIR /home/user/ 99 | VOLUME ["/home/user/app/"] 100 | 101 | CMD ["/bin/bash", "-l"] 102 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nimcache/ 2 | nimblecache/ 3 | htmldocs/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nephyr 2 | 3 | Nim interface and library for Zephyr RTOS. Run Nim on any microcontroller Zephyr supports! 4 | 5 | WIP! The API and package layout are still prone to large changes. That being said, it's possible to run Nim code on Zephyr and once it compiles it's appears very stable. 6 | 7 | ## Setup 8 | 9 | 1. Install Nim (recommend [choosenim](https://github.com/dom96/choosenim) ) 10 | - The Nim `devel` branch is currently required: `choosenim devel --latest` 11 | 3. Install Zephyr 12 | - `pip3 install west` 13 | - `west init -m https://github.com/EmbeddedNim/zephyr.git --mr nephyr-v2.7-branch-patched --narrow $HOME/zephyrproject/` 14 | - note there's work to improve this usine `nephyrcli` but it's not ready for public use yet 15 | 5. Recommended to install Nephyr using `nimble develop` as the library will be changing frequently: 16 | - `git clone https://github.com/EmbeddedNim/nephyr.git` 17 | - `cd nephyr/` 18 | - `nimble develop` 19 | 20 | ## Layout 21 | 22 | The library layout is broken into two main portions: 23 | - Nim apis under `src/nephyr/` 24 | - C Wrappers under `src/zephyr/` 25 | 26 | ## Examples 27 | 28 | See [Nephyr Examples repo](https://github.com/EmbeddedNim/nephyr_examples) for examples. 29 | 30 | ## Why 31 | 32 | Zephyr is taking a great approach to modernize RTOS & embedded development. It has support from multiple MCU vendors (NXP, Nordic, TI, etc). In some areas it's still less mature than other RTOS options, however it's rapidly improving and already boasts support for most modern MCU's. It also includes a bootloader, device drivers, and first class CI and testing. The primary downside is the lack of documentation especially when combined with the complicated nature of a very configurable RTOS. 33 | 34 | Nephyr's goal is to provide a stable high-level wrapper around Zephyr. However, the hardware APIs are being designed with being compatible with other RTOS'es. Eventually Nim could replace parts of Zephyr C stack with pure Nim solutions. 35 | 36 | 37 | ## Status 38 | 39 | ### Working 40 | 41 | - [x] Zephyr networking via POSIX layer 42 | - [x] Support for using Zephyr sockets & poll 43 | - [x] Nim wrappers for the basics of Zephyr devices and device tree 44 | - [x] Support for Firmware OTA updates using Nim 45 | - [x] I2C works and tested with real devices 46 | - [x] SPI raw api works, Nim SPI api is written but not verified 47 | - [x] Basic set of boards working with Nephyr out-of-the-box 48 | + nrf52480, STM32-H7 "Disco Boards", Teensy 4 (WIP) 49 | 50 | ### Ongoing 51 | 52 | - [ ] Documentation! 53 | - [ ] Significantly improve the Nim interface to the DTS system in Zephyr 54 | - [ ] Setup auto-installer for Zephyr 55 | - [ ] Setup CI builds with Zephyr 56 | - [ ] Setup CI run tests using QEMU 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /config.nims: -------------------------------------------------------------------------------- 1 | 2 | --gc:arc -------------------------------------------------------------------------------- /nephyr.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "0.3.2" 4 | author = "Jaremy J. Creechley" 5 | description = "Nim wrapper for Zephyr RTOS" 6 | license = "Apache-2.0" 7 | srcDir = "src" 8 | 9 | # Dependencies 10 | 11 | requires "nim >= 1.6.5" 12 | requires "msgpack4nim >= 0.3.1" 13 | requires "stew >= 0.1.0" 14 | requires "cdecl >= 0.4.5" 15 | requires "https://github.com/EmbeddedNim/nephyrcli >= 0.3.1" 16 | requires "mcu_utils >= 0.3.3" 17 | requires "fastrpc >= 0.2.0" 18 | 19 | 20 | import os, sequtils, sugar 21 | 22 | task test_nim_api_compilation, "compile Nim wrapper apis": 23 | let api_test_files = "tests/drivers/".listFiles() 24 | for test in api_test_files: 25 | if test.startsWith("t") and test.endswith(".nim") == false: continue 26 | exec "nim c --compileonly:on " & test 27 | 28 | task test_zephyr_c_api, "compile Zephyr wrapper apis": 29 | let main_files = "src/nephyr/zephyr/".listFiles() 30 | let kernel_files = "src/nephyr/zephyr/kernel/".listFiles() 31 | let dt_files = "src/nephyr/zephyr/dt_bindings/".listFiles() 32 | let driver_files = "src/nephyr/zephyr/drivers/".listFiles() 33 | 34 | let all_tests = concat(main_files, kernel_files, dt_files, driver_files) 35 | dump all_tests 36 | for test in all_tests: 37 | if not test.endswith(".nim"): continue 38 | let cmd = "nim c --compileonly:on " & test 39 | exec(cmd) 40 | 41 | task unit_tests, "unit tests": 42 | exec("nim c -r tests/unit_tests/t_nvs_cfg_obj.nim") 43 | 44 | before test: 45 | test_zephyr_c_apiTask() 46 | test_nim_api_compilationTask() -------------------------------------------------------------------------------- /nims.cfg: -------------------------------------------------------------------------------- 1 | 2 | --os:linux 3 | 4 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | !* 2 | *.nim 3 | *.nims 4 | -------------------------------------------------------------------------------- /src/nephyr.nim: -------------------------------------------------------------------------------- 1 | 2 | import macros 3 | from os import getEnv, `/` 4 | 5 | import nephyr/general 6 | 7 | export general 8 | 9 | include mcu_utils/threads 10 | 11 | import macros 12 | import strformat 13 | 14 | proc NimMain() {.importc.} 15 | 16 | template wrappAllErrors*(name: string, procBody: untyped): untyped = 17 | try: 18 | `procBody` 19 | except Exception as e: 20 | ## manually print stack to handle lower memory devices 21 | echo "[" & name & "]: exception: ", getCurrentExceptionMsg() 22 | let stes = getStackTraceEntries(e) 23 | for ste in stes: 24 | echo "[" & name & "]: ", $ste 25 | except Defect as e: 26 | ## manually print stack to handle lower memory devices 27 | echo "[" & name & "]: defect: ", getCurrentExceptionMsg() 28 | let stes = getStackTraceEntries(e) 29 | for ste in stes: 30 | echo "[" & name & "]: ", $ste 31 | 32 | macro zephyr_main*(p: untyped): untyped = 33 | ## default wrapper that wraps exceptions and prints them out. 34 | ## 35 | ## This exports the annotated proc with `exportc`. 36 | ## 37 | result = p 38 | const 39 | pragmaIdx = 4 40 | procBodyIdx = 6 41 | let 42 | procBody = p[procBodyIdx] 43 | 44 | # add `exportc` pragma 45 | result[pragmaIdx] = nnkPragma.newTree(ident("exportc")) 46 | 47 | # wrap c body 48 | result[procBodyIdx] = quote do: 49 | NimMain() # initialize garbage collector memory, types and stack 50 | wrappAllErrors("main", `procBody`) 51 | echo "unknown error causing reboot" 52 | # sysReboot() 53 | sysPanic() 54 | 55 | 56 | 57 | template app_main*(blk: untyped): untyped = 58 | app_main(0, blk) 59 | 60 | 61 | template app_main*(delayms: static[int], blk: untyped): untyped = 62 | 63 | proc main*() {.exportc.} = 64 | when delayms > 0: 65 | os.sleep(delayms) 66 | NimMain() # initialize garbage collector memory, types and stack 67 | try: 68 | blk 69 | except: 70 | echo "Error: " 71 | echo getCurrentExceptionMsg() 72 | abort() -------------------------------------------------------------------------------- /src/nephyr/board_fixes.nim: -------------------------------------------------------------------------------- 1 | import zconsts 2 | import general 3 | 4 | static: 5 | echo "Board FIXUP: ", BOARD 6 | 7 | when isMainModule: 8 | when BOARD in ["teensy40", "teensy41"]: 9 | 10 | ## Change Teensy PinMux to use CS GPIO Pin 11 | proc board_configuration() {.exportc.} = 12 | {.emit: """ 13 | // configure pin mux for LP-SPI CS pins to be a regular gpio pins 14 | // allowing them to be controlled by Zephyr SPI driver and not NXP lpSPI hardware 15 | IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_03_GPIO1_IO03, 0); 16 | IOMUXC_SetPinMux(IOMUXC_GPIO_B0_00_GPIO2_IO00, 0); 17 | """.} 18 | 19 | # call zephyr `SYS_INIT` mode 20 | {.emit: "/*INCLUDESECTION*/\n#include ".} 21 | SystemInit(board_configuration, INIT_PRE_KERNEL_1, KernelInitPriorityDefault) 22 | 23 | elif BOARD == "": 24 | static: 25 | raise newException(Exception, "board must be selected. Board was set to: " & BOARD) 26 | 27 | -------------------------------------------------------------------------------- /src/nephyr/core/zchannel.nim: -------------------------------------------------------------------------------- 1 | 2 | from macros import error 3 | import std/atomics 4 | 5 | import ../zephyr/kernel/zk_fifo 6 | 7 | type 8 | 9 | item*[TMsg] {.gcsafe.} = object ## a ZChannel for thread communication 10 | k_reserved: pointer # for Zephyr kernel bookkeeping 11 | data: TMsg 12 | 13 | ZChannel*[TMsg] {.gcsafe.} = object ## a ZChannel for thread communication 14 | k_fifo: k_fifo 15 | limit: Atomic[int] 16 | 17 | 18 | when not defined(gcDestructors): 19 | error("must use GC with destructors") 20 | 21 | proc initZkFifo*[TMsg](): ZChannel[TMsg] = 22 | k_fifo_init(addr result.k_fifo) 23 | 24 | proc sendImpl(q: PRawChannel, typ: PNimType, msg: pointer, noBlock: bool): bool = 25 | if q.mask == ChannelDeadMask: 26 | sysFatal(DeadThreadDefect, "cannot send message; thread died") 27 | acquireSys(q.lock) 28 | if q.maxItems > 0: 29 | # Wait until count is less than maxItems 30 | if noBlock and q.count >= q.maxItems: 31 | releaseSys(q.lock) 32 | return 33 | 34 | while q.count >= q.maxItems: 35 | waitSysCond(q.cond, q.lock) 36 | 37 | rawSend(q, msg, typ) 38 | q.elemType = typ 39 | releaseSys(q.lock) 40 | signalSysCond(q.cond) 41 | result = true 42 | 43 | proc send*[TMsg](c: var ZChannel[TMsg], msg: sink TMsg) {.inline.} = 44 | ## Sends a message to a thread. `msg` is deeply copied. 45 | # discard sendImpl(cast[PRawChannel](addr c), cast[PNimType](getTypeInfo(msg)), unsafeAddr(msg), false) 46 | wasMoved(msg) 47 | 48 | proc trySend*[TMsg](c: var ZChannel[TMsg], msg: sink TMsg): bool {.inline.} = 49 | ## Tries to send a message to a thread. 50 | ## 51 | ## `msg` is deeply copied. Doesn't block. 52 | ## 53 | ## Returns `false` if the message was not sent because number of pending items 54 | ## in the ZChannel exceeded `maxItems`. 55 | result = sendImpl(cast[PRawChannel](addr c), cast[PNimType](getTypeInfo(msg)), unsafeAddr(msg), true) 56 | if result: 57 | wasMoved(msg) 58 | 59 | proc recv*[TMsg](c: var ZChannel[TMsg]): TMsg = 60 | ## Receives a message from the ZChannel `c`. 61 | ## 62 | ## This blocks until a message has arrived! 63 | ## You may use `peek proc <#peek,ZChannel[TMsg]>`_ to avoid the blocking. 64 | var q = cast[PRawChannel](addr(c)) 65 | acquireSys(q.lock) 66 | llRecv(q, addr(result), cast[PNimType](getTypeInfo(result))) 67 | releaseSys(q.lock) 68 | 69 | proc tryRecv*[TMsg](c: var ZChannel[TMsg]): tuple[dataAvailable: bool, 70 | msg: TMsg] = 71 | ## Tries to receive a message from the ZChannel `c`, but this can fail 72 | ## for all sort of reasons, including contention. 73 | ## 74 | ## If it fails, it returns `(false, default(msg))` otherwise it 75 | ## returns `(true, msg)`. 76 | var q = cast[PRawChannel](addr(c)) 77 | 78 | proc peekHead*[TMsg](c: var ZChannel[TMsg]): int = 79 | ## Returns the current number of messages in the ZChannel `c`. 80 | ## 81 | ## Returns -1 if the ZChannel has been closed. 82 | ## 83 | ## **Note**: This is dangerous to use as it encourages races. 84 | ## It's much better to use `tryRecv proc <#tryRecv,ZChannel[TMsg]>`_ instead. 85 | var q = cast[PRawChannel](addr(c)) 86 | 87 | proc peekTail*[TMsg](c: var ZChannel[TMsg]): int = 88 | var q = cast[PRawChannel](addr(c)) 89 | 90 | proc peek*[TMsg](c: var ZChannel[TMsg]): int = 91 | ## Returns the current number of messages in the ZChannel `c`. 92 | ## 93 | ## Returns -1 if the ZChannel has been closed. 94 | ## 95 | ## **Note**: This is dangerous to use as it encourages races. 96 | ## It's much better to use `tryRecv proc <#tryRecv,ZChannel[TMsg]>`_ instead. 97 | return peekTail(c) 98 | 99 | proc open*[TMsg](c: var ZChannel[TMsg], maxItems: int = 0) = 100 | ## Opens a ZChannel `c` for inter thread communication. 101 | ## 102 | ## The `send` operation will block until number of unprocessed items is 103 | ## less than `maxItems`. 104 | ## 105 | ## For unlimited queue set `maxItems` to 0. 106 | initRawChannel(addr(c), maxItems) 107 | 108 | proc close*[TMsg](c: var ZChannel[TMsg]) = 109 | ## Closes a ZChannel `c` and frees its associated resources. 110 | 111 | proc ready*[TMsg](c: var ZChannel[TMsg]): bool = 112 | ## Returns true if some thread is waiting on the ZChannel `c` for 113 | ## new messages. 114 | var q = cast[PRawChannel](addr(c)) 115 | result = q.ready 116 | -------------------------------------------------------------------------------- /src/nephyr/devices.nim: -------------------------------------------------------------------------------- 1 | import zephyr/zkernel_fixes 2 | import zephyr/zconfs 3 | import zephyr/zdevice 4 | import zephyr/zkernel 5 | import zephyr/kernel/zk_locks 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/nephyr/drivers/Pins.nim: -------------------------------------------------------------------------------- 1 | 2 | import ../zephyr/drivers/zgpio 3 | 4 | type 5 | GpioPin* = gpio_pin_t 6 | GpioFlags* = gpio_flags_t 7 | 8 | const 9 | 10 | IN* = GpioFlags GPIO_INPUT ## Configure pin in input mode 11 | OUT* = GpioFlags GPIO_OUTPUT ## Configure pin in output mode 12 | OFF* = GpioFlags 0 ## Disables pin for both input and output 13 | 14 | OUT_LOW* = GpioFlags GPIO_OUTPUT_LOW ## * Configures pin as output and initializes it to a low state 15 | OUT_HIGH* = GpioFlags GPIO_OUTPUT_HIGH ## * Configures pin as output and initializes it to a high state 16 | 17 | OUT_INACTIVE* = GpioFlags GPIO_OUTPUT_INACTIVE ## Configures pin as output and initializes it to a logic 0 18 | OUT_ACTIVE* = GpioFlags GPIO_OUTPUT_ACTIVE ## Configures pin as output and initializes it to a logic 1. 19 | -------------------------------------------------------------------------------- /src/nephyr/drivers/device.nim: -------------------------------------------------------------------------------- 1 | import ../zephyr/zdevice 2 | 3 | proc z_device_get_all_static*(device: ptr UncheckedArray[ptr device]): csize_t {. 4 | importc: "z_device_get_all_static", header: "device.h".} ##\ 5 | ## @brief Get access to the static array of static devices. 6 | ## 7 | ## @param devices where to store the pointer to the array of 8 | ## statically allocated devices. The array must not be mutated 9 | ## through this pointer. 10 | ## * 11 | ## @return the number of statically allocated devices. 12 | ## 13 | 14 | proc listAllStaticDevices*(): seq[ptr device] = 15 | var sdevs: ptr UncheckedArray[ptr device] 16 | var cnt: csize_t 17 | cnt = z_device_get_all_static(sdevs) 18 | echo "cnt: ", cnt 19 | newSeq(result, cnt) 20 | for i in 0.. 0: 48 | result.fs.sector_size = sectorSize.uint16 49 | logDebug fmt"calling flash info: {result.fs.sector_size=}" 50 | else: 51 | logDebug fmt"calling flash info: " 52 | ## unless overrided, lookup sectorSize 53 | var info: flash_pages_info 54 | check: flash_get_page_info_by_offs( 55 | flash_dev, 56 | partitionOffset.cint, 57 | addr info) 58 | result.fs.sector_size = info.size.uint16 59 | logDebug fmt"calling flash info: {result.fs.sector_size=}" 60 | 61 | logDebug fmt"calling nvs_init " 62 | check: nvs_init(result.fs.addr, flash_dev.name) 63 | 64 | template initNvs*( 65 | flash: string, 66 | sectorCount: uint16, 67 | partitionName: static[string], 68 | isBits: static[bool] = false, 69 | ): NvsConfig = 70 | ## helper template that finds the flash partition offset 71 | let offsetRaw = FLASH_AREA_OFFSET(tok(partitionName)) 72 | let offset: BytesSz = when isBits: BytesSz(offsetRaw div 8) 73 | else: BytesSz(offsetRaw) 74 | initNvs(flash, sectorCount, offset) 75 | 76 | template readImpl[T](nvs: NvsConfig, id: NvsId, item: ptr T) = 77 | let resCnt = nvs_read(nvs.fs.addr, id.uint16, item, sizeof((T))) 78 | if resCnt == -ENOENT: 79 | raise newException(KeyError, "missing key") 80 | elif resCnt < 0: 81 | raiseOSError(resCnt.OSErrorCode, "error reading nvs") 82 | elif resCnt != sizeof(T): 83 | raise newException(ValueError, "read wrong number of bytes: " & $resCnt & "/" & $sizeof(T)) 84 | 85 | proc read*[T](nvs: NvsConfig, id: NvsId, item: var ref T) = 86 | if item == nil: 87 | new(item) 88 | readImpl(nvs, id, addr(item[])) 89 | 90 | proc read*[T](nvs: NvsConfig, id: NvsId, item: var T) = 91 | readImpl(nvs, id, item.addr) 92 | 93 | proc read*[T](nvs: NvsConfig, id: NvsId, kind: typedesc[ref T]): ref T = 94 | new(result) 95 | readImpl(nvs, id, result[].addr) 96 | 97 | proc read*[T](nvs: NvsConfig, id: NvsId, kind: typedesc[T]): T = 98 | readImpl(nvs, id, result.addr) 99 | 100 | proc writeImpl[T](nvs: NvsConfig, id: NvsId, item: ptr T): bool {.discardable.} = 101 | let resCnt = nvs_write(nvs.fs.addr, id.uint16, item, sizeof((T))) 102 | if resCnt < 0: 103 | raiseOSError(resCnt.OSErrorCode, "error reading nvs") 104 | elif resCnt == 0: 105 | return false 106 | elif resCnt != sizeof(T): 107 | raise newException(ValueError, "wrote wrong number of bytes: " & $resCnt & "/" & $sizeof(T)) 108 | result = true 109 | 110 | proc write*[T](nvs: NvsConfig, id: NvsId, item: ref T) = 111 | writeImpl(nvs, id, unsafeAddr(item[])) 112 | 113 | proc write*[T](nvs: NvsConfig, id: NvsId, item: T) = 114 | writeImpl(nvs, id, item.unsafeAddr) 115 | -------------------------------------------------------------------------------- /src/nephyr/drivers/spi.nim: -------------------------------------------------------------------------------- 1 | import macros 2 | 3 | import nephyr/general 4 | import ../zephyr/zcmtoken 5 | import ../zephyr/zdevicetree 6 | import ../zephyr/drivers/zgpio 7 | import ../zephyr/drivers/zspi 8 | import ../zephyr/dt_bindings/dt_gpio 9 | import ../zephyr/dt_bindings/dt_spi 10 | 11 | export zgpio 12 | export zspi 13 | export dt_gpio, dt_spi 14 | export utils, zcmtoken, zdevice, zdevicetree 15 | 16 | type 17 | 18 | SpiReg8* = uint8 19 | SpiReg* = SpiReg8 20 | SpiReg16* = uint16 21 | SpiRegister* = SpiReg8 | SpiReg16 22 | 23 | SpiDevice* = ref object 24 | cfg*: spi_config 25 | bus*: ptr device 26 | 27 | proc initSpiDevice*(bus: ptr device, 28 | cs_ctrl: ptr spi_cs_control, 29 | operation: uint16, 30 | frequency: Hertz, 31 | slave = 0'u16, 32 | ): SpiDevice = 33 | if result.bus.isNil(): 34 | let emsg = 35 | when typeof(bus) is cstring: 36 | "error finding spi device: " & $dev 37 | elif typeof(bus) is cminvtoken: 38 | "error finding spi device: " & dev.toString() 39 | elif typeof(bus) is ptr device: 40 | "error finding spi device: 0x" & $(cast[int](bus).toHex()) 41 | raise newException(OSError, emsg) 42 | 43 | result = SpiDevice() 44 | result.bus = bus 45 | result.cfg = spi_config( 46 | frequency: frequency.uint32, 47 | operation: operation, 48 | slave: slave, # TODO 49 | cs: cs_ctrl 50 | ) 51 | 52 | template DtSpiDevice*(dev: untyped): untyped = 53 | var devptr: ptr device 54 | when typeof(dev) is cstring: 55 | devptr = device_get_binding(dev) 56 | when typeof(dev) is cminvtoken: 57 | devptr = DEVICE_DT_GET(DT_NODELABEL(dev)) 58 | elif typeof(dev) is ptr device: 59 | devptr = dev 60 | 61 | devptr 62 | 63 | template DtSpiCsDevice*(cs_name: untyped, cs_idx: untyped): ptr spi_cs_control = 64 | SPI_CS_CONTROL_PTR_DT(DT_NODELABEL(cs_name), cs_idx) 65 | 66 | proc read*(txbuf, rxbuf: var spi_buf; data: var openArray[uint8]) = 67 | # Create a read-only transaction 68 | txbuf.buf = nil 69 | txbuf.len = 0 70 | rxbuf.buf = unsafeAddr data[0] 71 | rxbuf.len = data.lenBytes() 72 | 73 | proc write*(txbuf, rxbuf: var spi_buf; data: openArray[uint8]) = 74 | # Create a write-only transaction 75 | txbuf.buf = unsafeAddr data[0] 76 | txbuf.len = data.lenBytes() 77 | rxbuf.buf = nil 78 | rxbuf.len = 0 79 | 80 | proc readWrite*(txbuf, rxbuf: var spi_buf; readData: var openArray[uint8], writeData: openArray[uint8]) = 81 | # Create a write-read transaction 82 | txbuf.buf = unsafeAddr writeData[0] 83 | txbuf.len = writeData.lenBytes() 84 | rxbuf.buf = unsafeAddr readData[0] 85 | rxbuf.len = readData.lenBytes() 86 | 87 | 88 | macro doTransfers*(dev: var SpiDevice, args: varargs[untyped]) = 89 | ## performs an i2c transfer by iterating through the arguments 90 | ## which should be proc's that take an i2c_msg var and 91 | ## sets it up. 92 | ## 93 | ## Example usage: 94 | ## var dev = i2c_devptr() 95 | ## var data: array[3, uint8] 96 | ## dev.doTransfer( 97 | ## reg(I2cReg16(0x4ffd)), 98 | ## read(data), 99 | ## write([0x1'u8, 0x2], I2C_MSG_STOP)) 100 | ## 101 | result = newStmtList() 102 | 103 | if args.len() == 0: 104 | result.add quote do: 105 | check: i2c_transfer(`dev`.bus, nil, 0, `dev`.address.uint16) 106 | return 107 | 108 | # create the new i2cmsg array 109 | let 110 | mcnt = newIntLitNode(args.len()) 111 | txvar = genSym(nskVar, "tx_bufs") 112 | rxvar = genSym(nskVar, "rx_bufs") 113 | 114 | result.add quote do: 115 | var `txvar`: array[`mcnt`, spi_buf] 116 | var `rxvar`: array[`mcnt`, spi_buf] 117 | args.expectKind(nnkArglist) 118 | 119 | # applies array elements to each arg in turn 120 | for idx in 0.. {rval}") 68 | setObjectField(settings.values, name, rval) 69 | except KeyError: 70 | logDebug("CFG", "skipping name: %s", $name) 71 | 72 | proc saveField*[T]( 73 | settings: var ConfigSettings[T], 74 | name: string, 75 | val: int32, 76 | oldVal = none(int32) 77 | ) = 78 | var mName = mangleFieldName(name) 79 | var shouldWrite = if oldVal.isSome(): val != oldVal.get() 80 | else: true 81 | 82 | if shouldWrite: 83 | logDebug("CFG", fmt"save setting field: {name}({$mName}) => {oldVal=} -> {val=}") 84 | settings.store.write(mName, val) 85 | else: 86 | logDebug("CFG", fmt"skipping setting field: {name}({$mName}) => {oldVal=} -> {val=}") 87 | 88 | proc loadAll*[T](settings: var ConfigSettings[T]) = 89 | for name, val in settings.values.fieldPairs(): 90 | discard settings.loadField(name) 91 | 92 | proc saveAll*[T](ns: var ConfigSettings[T]) = 93 | logDebug("CFG", "saving settings ") 94 | for name, val in ns.values.fieldPairs(): 95 | ns.saveField(name, cast[int32](val)) 96 | 97 | proc newConfigSettings*[T](nvs: NvsConfig, config: T): ConfigSettings[T] = 98 | new(result) 99 | result.store = nvs 100 | result.values = config 101 | -------------------------------------------------------------------------------- /src/nephyr/general.nim: -------------------------------------------------------------------------------- 1 | 2 | import std/sequtils, std/strutils 3 | 4 | import mcu_utils/basictypes 5 | import mcu_utils/logging 6 | 7 | export basictypes 8 | export sequtils 9 | export strutils 10 | 11 | # nephyr modules 12 | import utils, logs 13 | import zephyr/zkernel 14 | import zephyr/kernel/zk_time 15 | 16 | export zkernel 17 | export utils 18 | export logs 19 | 20 | from os import raiseOSError 21 | export raiseOSError 22 | 23 | from posix import ENOENT, EIO, EAGAIN, EFAULT, EDOM 24 | export ENOENT, EIO, EAGAIN, EFAULT, EDOM 25 | 26 | type 27 | NephyrError* = object of Exception 28 | 29 | proc sysReboot*(coldReboot: bool = false) = k_sys_reboot(if coldReboot: 1 else: 0) 30 | proc sysPanic*(reason: k_fatal_error_reason | cuint) = k_fatal_halt(reason.cuint) 31 | proc sysPanic*() = k_fatal_halt(K_ERR_KERNEL_PANIC.cuint) 32 | 33 | proc usb_enable*(arg: pointer): cint {.importc: "usb_enable", header: "".} 34 | 35 | template sysUsbEnable*(arg: pointer = nil, check = false) = 36 | let res = usb_enable(arg) 37 | logWarn("sysUsbEnable:error: ", res) 38 | if check: 39 | doCheck(res) 40 | 41 | proc hwinfo_get_device_id*(buffer: cstring, length: csize_t) {.importc: "$1", header: "".} 42 | 43 | proc getDeviceId*(size = 64): string = 44 | result = newString(size) 45 | hwinfo_get_device_id(result.cstring, size.csize_t) 46 | 47 | type 48 | SystemInitLevel* = distinct int 49 | SystemInitPriority* = distinct int 50 | 51 | ThreadPriority* = distinct range[-128..128] 52 | BytesSz* = distinct int 53 | 54 | var INIT_PRE_KERNEL_1* {.importc: "PRE_KERNEL_1", header: "".}: SystemInitLevel 55 | var INIT_PRE_KERNEL_2* {.importc: "PRE_KERNEL_2", header: "".}: SystemInitLevel 56 | var INIT_POST_KERNEL* {.importc: "POST_KERNEL", header: "".}: SystemInitLevel 57 | var INIT_APPLICATION* {.importc: "APPLICATION", header: "".}: SystemInitLevel 58 | 59 | var KernelInitPriorityDefault* {.importc: "CONFIG_KERNEL_INIT_PRIORITY_DEFAULT", header: "".}: SystemInitPriority 60 | var KernelInitPriorityDevice* {.importc: "CONFIG_KERNEL_INIT_PRIORITY_DEVICE", header: "".}: SystemInitPriority 61 | var KernelInitPriorityObjects* {.importc: "CONFIG_KERNEL_INIT_PRIORITY_OBJECTS", header: "".}: SystemInitPriority 62 | 63 | template SystemInit*(fn: proc {.cdecl.}, level: SystemInitLevel, priority: SystemInitPriority) = 64 | ## Template to setup a zephyr initialization callback for a given level and priority. 65 | {.emit: "/*INCLUDESECTION*/\n#include ".} 66 | {.emit: ["/*VARSECTION*/\nSYS_INIT(", fn, ", ", level, ", ", priority, ");"].} 67 | 68 | macro zkThread*(p: untyped) = result = p 69 | 70 | proc kCreateThread*( 71 | thread: var k_thread; 72 | function: proc (p1, p2, p3: pointer) {.cdecl.}; 73 | stack: ptr k_thread_stack_t; 74 | stack_size: BytesSz; 75 | p1: pointer = nil, 76 | p2: pointer = nil, 77 | p3: pointer = nil, 78 | priority = ThreadPriority 1, 79 | options: uint32 = 0; 80 | delay: k_timeout_t = K_NO_WAIT 81 | ): k_tid_t = 82 | ## convenience wrapper for createThread 83 | ## 84 | ## Usage: 85 | ## 86 | ## # Thread Definition 87 | ## const blinkStackSz = 8192.BytesSz 88 | ## KDefineStack(blinkStack, blinkStackSz.int) 89 | ## var blink {.exportc.}: k_thread 90 | ## 91 | ## # Create and start thread 92 | ## let blinkId = 93 | ## blink.kCreateThread( 94 | ## function = blinkThrFunc, 95 | ## stack = blinkStack, 96 | ## stack_size = blinkStackSz, 97 | ## priority = 2.ThreadPriority, 98 | ## ) 99 | 100 | let entry: k_thread_entry_t = function 101 | result = 102 | zkernel.k_thread_create( 103 | addr thread, 104 | stack, 105 | stack_size.csize_t, 106 | entry, 107 | p1, p2, p3, 108 | priority.cint, 109 | options, 110 | delay 111 | ) 112 | 113 | 114 | template staticKThread*( 115 | name: untyped, 116 | entry: proc (p1, p2, p3: pointer) {.cdecl.}; 117 | stack: static[BytesSz]; 118 | p1: pointer = nil, 119 | p2: pointer = nil, 120 | p3: pointer = nil, 121 | priority = ThreadPriority 1, 122 | options: uint32 = 0; 123 | delay: k_timeout_t = K_NO_WAIT 124 | ) = 125 | ## convenience template to setup new thread 126 | ## includes creating a static stack 127 | ## creates global variables: 128 | ## var nameStack*: ptr k_thread_stack_t 129 | ## var nameThr* {.exportc.}: k_thread 130 | ## var name*: k_tid_t 131 | ## 132 | KDefineStack(`name Stack`, stack.int) 133 | var `name Thr` {.inject, global, exportc.}: k_thread 134 | let `name` {.inject, used, global.}: k_tid_t = 135 | zkernel.k_thread_create( 136 | addr `name Thr`, 137 | `name Stack`, 138 | stack.csize_t, 139 | entry, 140 | p1, p2, p3, 141 | priority.cint, 142 | options, 143 | delay 144 | ) 145 | 146 | -------------------------------------------------------------------------------- /src/nephyr/logs.nim: -------------------------------------------------------------------------------- 1 | import strutils 2 | import system 3 | import sequtils 4 | 5 | import macros 6 | 7 | # const LOG_HDR = "" 8 | 9 | # proc loge*(formatstr: cstring) {.importc: "LOG_ERR", varargs, header: LOG_HDR.} 10 | # proc logw*(formatstr: cstring) {.importc: "LOG_WRN", varargs, header: LOG_HDR.} 11 | # proc logi*(formatstr: cstring) {.importc: "LOG_INF", varargs, header: LOG_HDR.} 12 | # proc logd*(formatstr: cstring) {.importc: "LOG_DBG", varargs, header: LOG_HDR.} 13 | 14 | macro debug(args: varargs[untyped]): untyped = 15 | # `args` is a collection of `NimNode` values that each contain the 16 | # AST for an argument of the macro. A macro always has to 17 | # return a `NimNode`. A node of kind `nnkStmtList` is suitable for 18 | # this use case. 19 | result = nnkStmtList.newTree() 20 | # iterate over any argument that is passed to this macro: 21 | # add a call to the statement list that writes the expression; 22 | # `toStrLit` converts an AST to its string representation: 23 | # result.add newCall("echo", newLit(n.repr), newLit(": "), newCall("$", n)) 24 | let v = args.mapIt(newCall("$", it)) 25 | result.add newCall("echo", v) 26 | 27 | 28 | template loge*(args: varargs[untyped]) = 29 | debug(args) 30 | template logw*(args: varargs[untyped]) = 31 | # debug(args) 32 | discard "ignore" 33 | template logi*(args: varargs[untyped]) = 34 | debug(args) 35 | # discard "ignore" 36 | template logd*(args: varargs[untyped]) = 37 | # debug(args) 38 | discard "ignore" 39 | 40 | # proc ldup*(str: cstring): cstring {.importc: "log_strdup", varargs, header: LOG_HDR.} 41 | proc ldup*(str: cstring): cstring = str 42 | proc ldup*(str: string): cstring = 43 | ldup(str.cstring()) 44 | 45 | when defined(zephyr): 46 | template initLogs*(name: string) = 47 | const 48 | modName = name 49 | logimpt = """ 50 | 51 | /* Display all messages, including debugging ones: */ 52 | #define LOG_LEVEL LOG_LEVEL_DBG 53 | #include 54 | /* Set the "module" for these log messages: */ 55 | #define LOG_MODULE_NAME socket_net_nim 56 | 57 | LOG_MODULE_REGISTER($1); 58 | """ % [modName] 59 | {.emit: logimpt.} 60 | 61 | else: 62 | 63 | template initLogs*(name: string) = 64 | discard name 65 | -------------------------------------------------------------------------------- /src/nephyr/nets.nim: -------------------------------------------------------------------------------- 1 | import std/[net, os, tables] 2 | 3 | import mcu_utils/logging 4 | 5 | import zephyr/net/znet_linkaddr 6 | import zephyr/net/znet_ip 7 | import zephyr/net/znet_if 8 | import zephyr/net/znet_config 9 | import zephyr/net/zipv6 10 | 11 | export znet_linkaddr, znet_ip, znet_if, znet_config, zipv6 12 | 13 | import std/posix 14 | import std/nativesockets 15 | 16 | export posix, nativesockets, net 17 | 18 | import mcu_utils/nettypes 19 | 20 | # void net_if_foreach(net_if_cb_t cb, void *user_data) 21 | proc zfind_interfaces(iface: ptr net_if; user_data: pointer) {.cdecl, exportc.} = 22 | var table = cast[TableRef[NetIfId, NetIfDevice]](user_data) 23 | let nid = NetIfId(table.len()) 24 | let nif = NetIfDevice(raw: iface) 25 | table[nid] = nif 26 | 27 | proc findAllInterfaces*(): TableRef[NetIfId, NetIfDevice] = 28 | ## Finds all current network interfaces 29 | let cb: net_if_cb_t = zfind_interfaces 30 | result = newTable[NetIfId, NetIfDevice]() 31 | net_if_foreach(cb, cast[pointer](result)) 32 | 33 | proc hasDefaultInterface*(): bool = 34 | ## check for default interface 35 | let iface: ptr net_if = net_if_get_default() 36 | result = not iface.isNil 37 | 38 | proc getDefaultInterface*(): NetIfDevice {.raises: [ValueError].} = 39 | ## get default interface 40 | let iface: ptr net_if = net_if_get_default() 41 | if iface.isNil: 42 | raise newException(ValueError, "no default interface") 43 | result = NetIfDevice(raw: iface) 44 | 45 | proc hwAddress*(ifdev: NetIfDevice): seq[uint8] = 46 | let ll_addr: net_linkaddr = ifdev.raw.if_dev.link_addr 47 | result = newSeq[uint8](ll_addr.len.int) 48 | copyMem(result[0].addr, ll_addr.caddr, ll_addr.len.int) 49 | 50 | proc hwMacAddress*(ifdev: NetIfDevice): array[6, uint8] = 51 | let hwaddr = ifdev.hwAddress() 52 | result[0..5] = hwaddr[0..5] 53 | 54 | proc linkLocalAddr*(ifdev: NetIfDevice): IpAddress {.raises: [ValueError].} = 55 | ## finds and returns link local address 56 | let lladdr: ptr In6Addr = net_if_ipv6_get_ll(ifdev.raw, NET_ADDR_ANY_STATE) 57 | 58 | if lladdr.isNil: 59 | raise newException(ValueError, "no ipv6 link-local addr") 60 | 61 | var 62 | saddr: Sockaddr_in6 63 | port: Port 64 | 65 | saddr.sin6_family = toInt(Domain.AF_INET6).TSa_Family 66 | saddr.sin6_addr = lladdr[] 67 | fromSockAddr(saddr, sizeof(saddr).SockLen, result, port) 68 | 69 | # proc setLinkLocalAddress*(ifdev: NetIfDevice, open) = 70 | # ## finds and returns link local address 71 | # let lladdr: ptr In6Addr = net_if_ipv6_get_ll(ifdev.raw, NET_ADDR_ANY_STATE) 72 | 73 | # if lladdr.isNil: 74 | # raise newException(ValueError, "no ipv6 link-local addr") 75 | 76 | # var 77 | # saddr: Sockaddr_in6 78 | # port: Port 79 | 80 | # saddr.sin6_family = toInt(Domain.AF_INET6).TSa_Family 81 | # saddr.sin6_addr = lladdr[] 82 | # fromSockAddr(saddr, sizeof(saddr).SockLen, result, port) 83 | -------------------------------------------------------------------------------- /src/nephyr/randoms.nim: -------------------------------------------------------------------------------- 1 | 2 | const hdr = "" 3 | 4 | proc sys_rand32_get*(): uint32 {.importc: "$1", header: hdr.} #\ 5 | #* @brief Return a 32-bit random value that should pass general 6 | #* randomness tests. 7 | 8 | 9 | proc sys_rand_get*(dst: pointer, length: csize_t) {.importc: "$1", header: hdr.} #\ 10 | #* @brief Fill the destination buffer with random data values that should 11 | #* pass general randomness tests. 12 | 13 | 14 | proc sys_csrand_get*(dst: pointer, length: csize_t): int {.importc: "$1", header: hdr.} #\ 15 | #* @brief Fill the destination buffer with cryptographically secure 16 | #* random data values. 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/nephyr/times.nim: -------------------------------------------------------------------------------- 1 | import std/[times, monotimes] 2 | import mcu_utils/basictypes 3 | 4 | import zephyr/zconfs 5 | import zephyr/zkernel 6 | 7 | import nephyr/general 8 | import nephyr/zephyr/kernel/zk_time 9 | 10 | export general, zk_time 11 | 12 | # from std/monotimes import MonoTime 13 | export times, monotimes 14 | 15 | export basictypes 16 | export MonoTime 17 | 18 | proc k_uptime_ticks*(): int64 {.importc: "$1", header: "kernel.h".} # 19 | 20 | proc k_uptime_get*(): int64 {.importc: "$1", header: "kernel.h".} # 21 | proc k_uptime_get_32*(): uint32 {.importc: "$1", header: "kernel.h".} # 22 | proc k_uptime_delta*(reftime: ptr int64): int64 {.importc: "$1", header: "kernel.h".} # 23 | 24 | proc k_cycle_get_32*(): uint32 {.importc: "$1", header: "kernel.h".} # 25 | proc k_cycle_get_64*(): uint32 {.importc: "$1", header: "kernel.h".} # 26 | 27 | proc k_ms_to_ticks_ceil32*(ts: uint64): uint64 {.importc: "$1", header: "kernel.h".} # 28 | proc k_cyc_to_us_floor64*(ts: uint64): uint64 {.importc: "$1", header: "kernel.h".} # 29 | 30 | proc millis*(): Millis = Millis(k_uptime_get()) 31 | 32 | when CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER: 33 | proc micros*(): Micros = Micros(k_cyc_to_us_floor64(k_cycle_get_64())) 34 | else: 35 | proc micros*(): Micros = Micros(k_cyc_to_us_floor64(k_cycle_get_32())) 36 | 37 | proc delay*(ms: Millis): Millis = 38 | ## Sleep for millis, return 0 if requested time elapsed, otherwise the number of millis remaining 39 | return k_msleep(ms.int32).Millis 40 | 41 | proc delay*(us: Micros): Micros = 42 | ## Sleep for micros, return 0 if requested time elapsed, otherwise the number of micros remaining 43 | return k_usleep(us.int32).Micros 44 | 45 | proc delayMillis*(ts: int): bool {.discardable.} = 46 | ## Sleep for millis, return false if woken up early 47 | let res = k_msleep(ts.int32) 48 | if res == 0: 49 | return true 50 | 51 | # proc sleep*(us: Micros) = 52 | # var remaining = us.int32 53 | # while remaining != 0: 54 | # remaining = k_msleep(remaining) 55 | 56 | # proc sleep*(ms: Millis) = 57 | # ## Sleep for micros 58 | # var remaining = ms.int32 59 | # while remaining != 0: 60 | # remaining = k_msleep(remaining) 61 | 62 | when defined(linux): 63 | type 64 | TimerId* = int 65 | elif defined(zephyr): 66 | type 67 | TimerId* = ptr k_timer 68 | 69 | type 70 | TimerFunc* = proc (timerid: TimerId) {.cdecl.} 71 | 72 | proc createTimer*(timer: var k_timer, cb: TimerFunc) = 73 | if cb != nil: 74 | k_timer_init(addr timer, cb, nil) 75 | 76 | proc toTimeout*(delay: static[Millis]): k_timeout_t = 77 | ## convert Millis to k_timeout_t 78 | when delay == -1.Millis: K_NO_WAIT 79 | else: K_MSEC(delay.int) 80 | proc toTimeout*(delay: Millis): k_timeout_t = 81 | ## convert Millis to k_timeout_t 82 | if delay.int == -1: K_NO_WAIT 83 | else: K_MSEC(delay.int) 84 | 85 | proc toTimeout*(delay: static[Micros]): k_timeout_t = 86 | ## convert Micros to k_timeout_t 87 | when delay == -1.Micros: result = K_NO_WAIT 88 | else: result = K_USEC(delay.int) 89 | proc toTimeout*(delay: Micros): k_timeout_t = 90 | ## convert Micros to k_timeout_t 91 | if delay.int == -1: result = K_NO_WAIT 92 | else: result = K_USEC(delay.int) 93 | 94 | proc start*(timer: var k_timer, 95 | duration = -1.Millis, 96 | period = -1.Millis) = 97 | let 98 | dts = if duration.int == -1: K_NO_WAIT else: K_MSEC(duration.int) 99 | pts = if period.int == -1: K_NO_WAIT else: K_MSEC(period.int) 100 | k_timer_start(addr timer, dts, pts) 101 | 102 | proc start*(timer: var k_timer, 103 | duration = -1.Micros, 104 | period = -1.Micros) = 105 | let 106 | dts = if duration.int == -1: K_NO_WAIT else: K_USEC(duration.int) 107 | pts = if period.int == -1: K_NO_WAIT else: K_USEC(period.int) 108 | k_timer_start(addr timer, dts, pts) 109 | -------------------------------------------------------------------------------- /src/nephyr/utils.nim: -------------------------------------------------------------------------------- 1 | 2 | type 3 | Bytes*[N: static[int]] = array[N, uint8] 4 | 5 | proc doCheck*(ret: int): int {.discardable.} = 6 | if ret != 0: 7 | raise newException(OSError, "error id: " & $(ret)) 8 | return ret 9 | 10 | template check*(blk: untyped) = 11 | doCheck(blk) 12 | 13 | template clen*(item: untyped): untyped = 14 | csize_t(len(item)) 15 | 16 | template ulen*(item: untyped): untyped = 17 | uint32(len(item)) 18 | 19 | template lenBytes*[T](item: openArray[T]): untyped = 20 | uint32(sizeof(T) * item.len()) 21 | 22 | template setOr*[T, F](flags: set[F]): T = 23 | var st: T 24 | for flg in flags: 25 | st = st or T(flg) 26 | st 27 | 28 | template bytes*(args: varargs[uint8]): openArray[uint8] = 29 | args 30 | 31 | proc joinBytes32*[T](bs: openArray[uint8], count: range[0..4], top=false): T = 32 | ## Join's an array of bytes into an integer 33 | var n = 0'u32 34 | let N = min(count, bs.len()) 35 | for i in 0 ..< N: 36 | n = (n shl 8) or bs[i] 37 | if top: 38 | n = n shl (32-N*8) 39 | return cast[T](n) 40 | 41 | proc joinBytes64*[T](bs: openArray[uint8], count: range[0..8], top=false): T = 42 | ## Join's an array of bytes into an integer 43 | var n = 0'u64 44 | let N = min(count, bs.len()) 45 | for i in 0 ..< N: 46 | n = (n shl 8) or bs[i] 47 | if top: 48 | n = n shl (64-N*8) 49 | return cast[T](n) 50 | 51 | proc splitBytes*[T](val: T, count: range[0..8], top=false): seq[byte] = 52 | ## Splits's an integer into an array of bytes 53 | let szT = sizeof(T) 54 | let N = min(count, szT) 55 | 56 | var x = val 57 | result = newSeqOfCap[byte](N) 58 | for i in 0 ..< N: 59 | if top == false: 60 | result.add(byte(x)) 61 | x = x shr 8 62 | else: 63 | result.add( byte(x shr (8*szT-8) )) 64 | x = x shl 8 65 | 66 | -------------------------------------------------------------------------------- /src/nephyr/zconsts.nim: -------------------------------------------------------------------------------- 1 | 2 | import zephyr/zconfs 3 | 4 | export zconfs 5 | 6 | const BOARD* {.strdefine.} = "" 7 | 8 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/drivers/zflash_img.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2017 Nordic Semiconductor ASA 3 | ## Copyright (c) 2017 Linaro Limited 4 | ## 5 | ## SPDX-License-Identifier: Apache-2.0 6 | ## 7 | 8 | const flshdr = "" 9 | 10 | var CONFIG_IMG_BLOCK_BUF_SIZE* {.importc: "CONFIG_IMG_BLOCK_BUF_SIZE", header: flshdr, nodecl.}: cint 11 | 12 | type 13 | flash_img_context* {.importc: "struct $1", header: flshdr, 14 | bycopy, incompleteStruct.} = object 15 | 16 | 17 | ## * 18 | ## @brief Structure for verify flash region integrity 19 | ## 20 | ## Match vector length is fixed and depends on size from hash algorithm used 21 | ## to verify flash integrity. The current available algorithm is SHA-256. 22 | ## 23 | type 24 | flash_img_check* {.importc: "struct flash_img_check", header: flshdr, 25 | bycopy, incompleteStruct.} = object 26 | 27 | ## * 28 | ## @brief Initialize context needed for writing the image to the flash. 29 | ## 30 | ## @param ctx context to be initialized 31 | ## @param area_id flash area id of partition where the image should be written 32 | ## 33 | ## @return 0 on success, negative errno code on fail 34 | ## 35 | proc flash_img_init_id*(ctx: ptr flash_img_context; area_id: uint8): cint {. 36 | importc: "flash_img_init_id", header: flshdr.} 37 | 38 | 39 | ## * 40 | ## @brief Initialize context needed for writing the image to the flash. 41 | ## 42 | ## @param ctx context to be initialized 43 | ## 44 | ## @return 0 on success, negative errno code on fail 45 | ## 46 | proc flash_img_init*(ctx: ptr flash_img_context): cint {.importc: "flash_img_init", header: flshdr.} 47 | 48 | 49 | ## * 50 | ## @brief Read number of bytes of the image written to the flash. 51 | ## 52 | ## @param ctx context 53 | ## 54 | ## @return Number of bytes written to the image flash. 55 | ## 56 | proc flash_img_bytes_written*(ctx: ptr flash_img_context): csize_t {. 57 | importc: "flash_img_bytes_written", header: flshdr.} 58 | 59 | 60 | ## * 61 | ## @brief Process input buffers to be written to the image slot 1. flash 62 | ## memory in single blocks. Will store remainder between calls. 63 | ## 64 | ## A final call to this function with flush set to true 65 | ## will write out the remaining block buffer to flash. Since flash is written to 66 | ## in blocks, the contents of flash from the last byte written up to the next 67 | ## multiple of CONFIG_IMG_BLOCK_BUF_SIZE is padded with 0xff. 68 | ## 69 | ## @param ctx context 70 | ## @param data data to write 71 | ## @param len Number of bytes to write 72 | ## @param flush when true this forces any buffered 73 | ## data to be written to flash 74 | ## 75 | ## @return 0 on success, negative errno code on fail 76 | ## 77 | proc flash_img_buffered_write*(ctx: ptr flash_img_context; data: ptr uint8; 78 | len: csize_t; flush: bool): cint {. 79 | importc: "flash_img_buffered_write", header: flshdr.} 80 | 81 | 82 | ## * 83 | ## @brief Verify flash memory length bytes integrity from a flash area. The 84 | ## start point is indicated by an offset value. 85 | ## 86 | ## @param[in] ctx context. 87 | ## @param[in] fic flash img check data. 88 | ## @param[in] area_id flash area id of partition where the image should be 89 | ## verified. 90 | ## 91 | ## @return 0 on success, negative errno code on fail 92 | ## 93 | proc flash_img_checks*(ctx: ptr flash_img_context; fic: ptr flash_img_check; 94 | area_id: uint8): cint {.importc: "flash_img_check", header: flshdr.} 95 | 96 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/drivers/znvs.nim: -------------------------------------------------------------------------------- 1 | import ../zkernel_fixes 2 | import ../zconfs 3 | import ../zdevice 4 | import ../zkernel 5 | import ../kernel/zk_locks 6 | 7 | import ./zflash 8 | 9 | export zkernel_fixes, zdevice, zkernel, zk_locks 10 | 11 | ## NVS: non volatile storage in flash 12 | ## 13 | 14 | const hdr = "" 15 | 16 | type 17 | nvs_fs* {.importc: "struct nvs_fs", header: hdr, bycopy, incompleteStruct.} = object ##\ 18 | ## * 19 | ## @brief Non-volatile Storage File system structure 20 | ## 21 | ## @param offset File system offset in flash 22 | ## @param ate_wra Allocation table entry write address. Addresses are stored as uint32: ## high 2 bytes correspond to the sector, low 2 bytes are the offset in the sector 23 | ## @param data_wra Data write address 24 | ## @param sector_size File system is split into sectors, each sector must be multiple of pagesize 25 | ## @param sector_count Number of sectors in the file systems 26 | ## @param ready Flag indicating if the filesystem is initialized 27 | ## @param nvs_lock Mutex 28 | ## @param flash_device Flash Device runtime structure 29 | ## @param flash_parameters Flash memory parameters structure 30 | offset* {.importc: "offset".}: off_t ## 31 | ate_wra* {.importc: "ate_wra".}: uint32 32 | data_wra* {.importc: "data_wra".}: uint32 33 | sector_size* {.importc: "sector_size".}: uint16 34 | sector_count* {.importc: "sector_count".}: uint16 35 | ready* {.importc: "ready".}: bool 36 | # nvs_lock* {.importc: "nvs_lock".}: k_mutex 37 | flash_device* {.importc: "flash_device".}: ptr device 38 | flash_parameters* {.importc: "flash_parameters".}: ptr flash_parameters 39 | 40 | 41 | proc nvs_init*(fs: ptr nvs_fs; dev_name: cstring): cint {.importc: "nvs_init", 42 | header: hdr.} ##\ 43 | ## Initializes a NVS file system in flash. 44 | ## 45 | ## @param fs Pointer to file system 46 | ## @param dev_name Pointer to flash device name 47 | ## @retval 0 Success 48 | ## @retval -ERRNO errno code if error 49 | ## 50 | 51 | 52 | proc nvs_mount*(fs: ptr nvs_fs): cint {.importc: "nvs_mount", header: hdr.} ##\ 53 | ## @brief nvs_mount 54 | ## 55 | ## Mount a NVS file system onto the flash device specified in @p fs. 56 | ## 57 | ## @param fs Pointer to file system 58 | ## @retval 0 Success 59 | ## @retval -ERRNO errno code if error 60 | ## 61 | 62 | 63 | proc nvs_clear*(fs: ptr nvs_fs): cint {.importc: "nvs_clear", header: hdr.} ##\ 64 | ## Clears the NVS file system from flash. 65 | ## @param fs Pointer to file system 66 | ## @retval 0 Success 67 | ## @retval -ERRNO errno code if error 68 | ## 69 | 70 | 71 | 72 | proc nvs_write*(fs: ptr nvs_fs; id: uint16; data: pointer; len: int): int {. 73 | importc: "nvs_write", header: hdr.} ##\ 74 | ## Write an entry to the file system. 75 | ## 76 | ## @param fs Pointer to file system 77 | ## @param id Id of the entry to be written 78 | ## @param data Pointer to the data to be written 79 | ## @param len Number of bytes to be written 80 | ## 81 | ## @return Number of bytes written. On success, it will be equal to the number of bytes requested 82 | ## to be written. When a rewrite of the same data already stored is attempted, nothing is written 83 | ## to flash, thus 0 is returned. On error, returns negative value of errno.h defined error codes. 84 | ## 85 | 86 | 87 | 88 | 89 | proc nvs_delete*(fs: ptr nvs_fs; id: uint16): cint {.importc: "nvs_delete", 90 | header: hdr.} ##\ 91 | ## Delete an entry from the file system 92 | ## 93 | ## @param fs Pointer to file system 94 | ## @param id Id of the entry to be deleted 95 | ## @retval 0 Success 96 | ## @retval -ERRNO errno code if error 97 | ## 98 | 99 | 100 | 101 | 102 | proc nvs_read*(fs: ptr nvs_fs; id: uint16; data: pointer; len: int): int {. 103 | importc: "nvs_read", header: hdr.} ##\ 104 | ## Read an entry from the file system. 105 | ## 106 | ## @param fs Pointer to file system 107 | ## @param id Id of the entry to be read 108 | ## @param data Pointer to data buffer 109 | ## @param len Number of bytes to be read 110 | ## 111 | ## @return Number of bytes read. On success, it will be equal to the number of bytes requested 112 | ## to be read. When the return value is larger than the number of bytes requested to read this 113 | ## indicates not all bytes were read, and more data is available. On error, returns negative 114 | ## value of errno.h defined error codes. 115 | ## 116 | 117 | 118 | 119 | 120 | proc nvs_read_hist*(fs: ptr nvs_fs; id: uint16; data: pointer; len: int; 121 | cnt: uint16): int {.importc: "nvs_read_hist", 122 | header: hdr.} ##\ 123 | ## Read a history entry from the file system. 124 | ## 125 | ## @param fs Pointer to file system 126 | ## @param id Id of the entry to be read 127 | ## @param data Pointer to data buffer 128 | ## @param len Number of bytes to be read 129 | ## @param cnt History counter: 0: latest entry, 1: one before latest ... 130 | ## 131 | ## @return Number of bytes read. On success, it will be equal to the number of bytes requested 132 | ## to be read. When the return value is larger than the number of bytes requested to read this 133 | ## indicates not all bytes were read, and more data is available. On error, returns negative 134 | ## value of errno.h defined error codes. 135 | ## 136 | 137 | 138 | 139 | proc nvs_calc_free_space*(fs: ptr nvs_fs): int {.importc: "nvs_calc_free_space", 140 | header: hdr.} ##\ 141 | ## Calculate the available free space in the file system. 142 | ## 143 | ## @param fs Pointer to file system 144 | ## 145 | ## @return Number of bytes free. On success, it will be equal to the number of bytes that can 146 | ## still be written to the file system. Calculating the free space is a time consuming operation, 147 | ## especially on spi flash. On error, returns negative value of errno.h defined error codes. 148 | ## 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_extras.nim: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | proc sys_kernel_version_get*(): uint32 {.importc: "sys_kernel_version_get", header: "".} 5 | 6 | proc SYS_KERNEL_VER_MAJOR*(ver: uint32): uint32 {.importc: "SYS_KERNEL_VER_MAJOR", header: "".} 7 | proc SYS_KERNEL_VER_MINOR*(ver: uint32): uint32 {.importc: "SYS_KERNEL_VER_MINOR", header: "".} 8 | proc SYS_KERNEL_VER_PATCHLEVEL*(ver: uint32): uint32 {.importc: "SYS_KERNEL_VER_PATCHLEVEL", header: "".} 9 | 10 | 11 | proc zKernelVersion*(): tuple[major: int, minor: int, patch: int] = 12 | let 13 | ver = sys_kernel_version_get() 14 | maj = ver.SYS_KERNEL_VER_MAJOR().int 15 | mnr = ver.SYS_KERNEL_VER_MINOR().int 16 | ptc = ver.SYS_KERNEL_VER_PATCHLEVEL().int 17 | return (major: maj.int, minor: mnr, patch: ptc) 18 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_fatal.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2019 Intel Corporation. 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | ## * @file 7 | ## @brief Fatal error functions 8 | ## 9 | 10 | ## * 11 | ## @defgroup fatal_apis Fatal error APIs 12 | ## @ingroup kernel_apis 13 | ## @{ 14 | ## 15 | 16 | type 17 | k_fatal_error_reason* {.size: sizeof(cint).} = enum 18 | K_ERR_CPU_EXCEPTION, ## * Generic CPU exception, not covered by other codes 19 | K_ERR_SPURIOUS_IRQ, ## * Unhandled hardware interrupt 20 | K_ERR_STACK_CHK_FAIL, ## * Faulting context overflowed its stack buffer 21 | K_ERR_KERNEL_OOPS, ## * Moderate severity software error 22 | K_ERR_KERNEL_PANIC ## * High severity software error 23 | 24 | z_arch_esf_t = distinct object 25 | 26 | ## * 27 | ## @brief Halt the system on a fatal error 28 | ## 29 | ## Invokes architecture-specific code to power off or halt the system in 30 | ## a low power state. Lacking that, lock interrupts and sit in an idle loop. 31 | ## 32 | ## @param reason Fatal exception reason code 33 | ## 34 | proc k_fatal_halt*(reason: cuint) {.importc: "k_fatal_halt", header: "fatal.h".} 35 | 36 | 37 | ## * 38 | ## @brief Fatal error policy handler 39 | ## 40 | ## This function is not invoked by application code, but is declared as a 41 | ## weak symbol so that applications may introduce their own policy. 42 | ## 43 | ## The default implementation of this function halts the system 44 | ## unconditionally. Depending on architecture support, this may be 45 | ## a simple infinite loop, power off the hardware, or exit an emulator. 46 | ## 47 | ## If this function returns, then the currently executing thread will be 48 | ## aborted. 49 | ## 50 | ## A few notes for custom implementations: 51 | ## 52 | ## - If the error is determined to be unrecoverable, LOG_PANIC() should be 53 | ## invoked to flush any pending logging buffers. 54 | ## - K_ERR_KERNEL_PANIC indicates a severe unrecoverable error in the kernel 55 | ## itself, and should not be considered recoverable. There is an assertion 56 | ## in z_fatal_error() to enforce this. 57 | ## - Even outside of a kernel panic, unless the fault occurred in user mode, 58 | ## the kernel itself may be in an inconsistent state, with API calls to 59 | ## kernel objects possibly exhibiting undefined behavior or triggering 60 | ## another exception. 61 | ## 62 | ## @param reason The reason for the fatal error 63 | ## @param esf Exception context, with details and partial or full register 64 | ## state when the error occurred. May in some cases be NULL. 65 | ## 66 | proc k_sys_fatal_error_handler*(reason: cuint; esf: ptr z_arch_esf_t) {. 67 | importc: "k_sys_fatal_error_handler", header: "fatal.h".} 68 | 69 | ## * 70 | ## Called by architecture code upon a fatal error. 71 | ## 72 | ## This function dumps out architecture-agnostic information about the error 73 | ## and then makes a policy decision on what to do by invoking 74 | ## k_sys_fatal_error_handler(). 75 | ## 76 | ## On architectures where k_thread_abort() never returns, this function 77 | ## never returns either. 78 | ## 79 | ## @param reason The reason for the fatal error 80 | ## @param esf Exception context, with details and partial or full register 81 | ## state when the error occurred. May in some cases be NULL. 82 | ## 83 | proc z_fatal_error*(reason: cuint; esf: ptr z_arch_esf_t) {.importc: "z_fatal_error", 84 | header: "fatal.h".} 85 | 86 | ## * @} 87 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_heap.nim: -------------------------------------------------------------------------------- 1 | import ../zkernel_fixes 2 | import ../sys/zsys_heap 3 | import ../zsys_clock 4 | 5 | type 6 | 7 | k_heap* {.importc: "k_heap", header: "kernel.h", bycopy.} = object 8 | ## kernel synchronized heap struct 9 | heap* {.importc: "heap".}: sys_heap 10 | wait_q* {.importc: "wait_q".}: z_wait_q_t 11 | lock* {.importc: "lock".}: k_spinlock 12 | 13 | ## @addtogroup heap_apis 14 | ## @{ 15 | ## 16 | 17 | ## * 18 | ## @brief Initialize a k_heap 19 | ## 20 | ## This constructs a synchronized k_heap object over a memory region 21 | ## specified by the user. Note that while any alignment and size can 22 | ## be passed as valid parameters, internal alignment restrictions 23 | ## inside the inner sys_heap mean that not all bytes may be usable as 24 | ## allocated memory. 25 | ## 26 | ## @param h Heap struct to initialize 27 | ## @param mem Pointer to memory. 28 | ## @param bytes Size of memory region, in bytes 29 | ## 30 | proc k_heap_init*(h: ptr k_heap; mem: pointer; bytes: csize_t) {. 31 | importc: "k_heap_init", header: "kernel.h".} 32 | 33 | 34 | ## * @brief Allocate aligned memory from a k_heap 35 | ## 36 | ## Behaves in all ways like k_heap_alloc(), except that the returned 37 | ## memory (if available) will have a starting address in memory which 38 | ## is a multiple of the specified power-of-two alignment value in 39 | ## bytes. The resulting memory can be returned to the heap using 40 | ## k_heap_free(). 41 | ## 42 | ## @note @a timeout must be set to K_NO_WAIT if called from ISR. 43 | ## @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT. 44 | ## 45 | ## @funcprops \isr_ok 46 | ## 47 | ## @param h Heap from which to allocate 48 | ## @param align Alignment in bytes, must be a power of two 49 | ## @param bytes Number of bytes requested 50 | ## @param timeout How long to wait, or K_NO_WAIT 51 | ## @return Pointer to memory the caller can now use 52 | ## 53 | proc k_heap_aligned_alloc*(h: ptr k_heap; align: csize_t; bytes: csize_t; 54 | timeout: k_timeout_t): pointer {. 55 | importc: "k_heap_aligned_alloc", header: "kernel.h".} 56 | 57 | 58 | ## * 59 | ## @brief Allocate memory from a k_heap 60 | ## 61 | ## Allocates and returns a memory buffer from the memory region owned 62 | ## by the heap. If no memory is available immediately, the call will 63 | ## block for the specified timeout (constructed via the standard 64 | ## timeout API, or K_NO_WAIT or K_FOREVER) waiting for memory to be 65 | ## freed. If the allocation cannot be performed by the expiration of 66 | ## the timeout, NULL will be returned. 67 | ## 68 | ## @note @a timeout must be set to K_NO_WAIT if called from ISR. 69 | ## @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT. 70 | ## 71 | ## @funcprops \isr_ok 72 | ## 73 | ## @param h Heap from which to allocate 74 | ## @param bytes Desired size of block to allocate 75 | ## @param timeout How long to wait, or K_NO_WAIT 76 | ## @return A pointer to valid heap memory, or NULL 77 | ## 78 | proc k_heap_alloc*(h: ptr k_heap; bytes: csize_t; timeout: k_timeout_t): pointer {. 79 | importc: "k_heap_alloc", header: "kernel.h".} 80 | 81 | 82 | ## * 83 | ## @brief Free memory allocated by k_heap_alloc() 84 | ## 85 | ## Returns the specified memory block, which must have been returned 86 | ## from k_heap_alloc(), to the heap for use by other callers. Passing 87 | ## a NULL block is legal, and has no effect. 88 | ## 89 | ## @param h Heap to which to return the memory 90 | ## @param mem A valid memory block, or NULL 91 | ## 92 | proc k_heap_free*(h: ptr k_heap; mem: pointer) {.importc: "k_heap_free", 93 | header: "kernel.h".} 94 | ## Hand-calculated minimum heap sizes needed to return a successful 95 | ## 1-byte allocation. See details in lib/os/heap.[ch] 96 | ## 97 | var Z_HEAP_MIN_SIZE* {.importc: "Z_HEAP_MIN_SIZE", header: "kernel.h".}: int 98 | ## * 99 | ## @brief Define a static k_heap in the specified linker section 100 | ## 101 | ## This macro defines and initializes a static memory region and 102 | ## k_heap of the requested size in the specified linker section. 103 | ## After kernel start, &name can be used as if k_heap_init() had 104 | ## been called. 105 | ## 106 | ## Note that this macro enforces a minimum size on the memory region 107 | ## to accommodate metadata requirements. Very small heaps will be 108 | ## padded to fit. 109 | ## 110 | ## @param name Symbol name for the struct k_heap object 111 | ## @param bytes Size of memory region, in bytes 112 | ## @param in_section __attribute__((section(name)) 113 | ## 114 | # proc Z_HEAP_DEFINE_IN_SECT*(name: cminvtoken; bytes: static[int]; in_section: cminvtoken) {. 115 | # importc: "Z_HEAP_DEFINE_IN_SECT", header: "kernel.h".} 116 | 117 | 118 | ## * 119 | ## @brief Define a static k_heap 120 | ## 121 | ## This macro defines and initializes a static memory region and 122 | ## k_heap of the requested size. After kernel start, &name can be 123 | ## used as if k_heap_init() had been called. 124 | ## 125 | ## Note that this macro enforces a minimum size on the memory region 126 | ## to accommodate metadata requirements. Very small heaps will be 127 | ## padded to fit. 128 | ## 129 | ## @param name Symbol name for the struct k_heap object 130 | ## @param bytes Size of memory region, in bytes 131 | ## 132 | proc K_HEAP_DEFINE*(name: cminvtoken; bytes: static[int]) {.importc: "K_HEAP_DEFINE", 133 | header: "kernel.h".} 134 | 135 | 136 | ## * 137 | ## @brief Define a static k_heap in uncached memory 138 | ## 139 | ## This macro defines and initializes a static memory region and 140 | ## k_heap of the requested size in uncache memory. After kernel 141 | ## start, &name can be used as if k_heap_init() had been called. 142 | ## 143 | ## Note that this macro enforces a minimum size on the memory region 144 | ## to accommodate metadata requirements. Very small heaps will be 145 | ## padded to fit. 146 | ## 147 | ## @param name Symbol name for the struct k_heap object 148 | ## @param bytes Size of memory region, in bytes 149 | ## 150 | proc K_HEAP_DEFINE_NOCACHE*(name: cminvtoken; bytes: static[int]) {. 151 | importc: "K_HEAP_DEFINE_NOCACHE", header: "kernel.h".} 152 | 153 | 154 | ## * 155 | ## @} 156 | ## 157 | ## * 158 | ## @defgroup heap_apis Heap APIs 159 | ## @ingroup kernel_apis 160 | ## @{ 161 | ## 162 | ## * 163 | ## @brief Allocate memory from the heap with a specified alignment. 164 | ## 165 | ## This routine provides semantics similar to aligned_alloc(); memory is 166 | ## allocated from the heap with a specified alignment. However, one minor 167 | ## difference is that k_aligned_alloc() accepts any non-zero @p size, 168 | ## wherase aligned_alloc() only accepts a @p size that is an integral 169 | ## multiple of @p align. 170 | ## 171 | ## Above, aligned_alloc() refers to: 172 | ## C11 standard (ISO/IEC 9899:2011): 7.22.3.1 173 | ## The aligned_alloc function (p: 347-348) 174 | ## 175 | ## @param align Alignment of memory requested (in bytes). 176 | ## @param size Amount of memory requested (in bytes). 177 | ## 178 | ## @return Address of the allocated memory if successful; otherwise NULL. 179 | ## 180 | proc k_aligned_alloc*(align: csize_t; size: csize_t): pointer {. 181 | importc: "k_aligned_alloc", header: "kernel.h".} 182 | 183 | 184 | ## * 185 | ## @brief Allocate memory from the heap. 186 | ## 187 | ## This routine provides traditional malloc() semantics. Memory is 188 | ## allocated from the heap memory pool. 189 | ## 190 | ## @param size Amount of memory requested (in bytes). 191 | ## 192 | ## @return Address of the allocated memory if successful; otherwise NULL. 193 | ## 194 | proc k_malloc*(size: csize_t): pointer {.importc: "k_malloc", header: "kernel.h".} 195 | 196 | 197 | ## * 198 | ## @brief Free memory allocated from heap. 199 | ## 200 | ## This routine provides traditional free() semantics. The memory being 201 | ## returned must have been allocated from the heap memory pool or 202 | ## k_mem_pool_malloc(). 203 | ## 204 | ## If @a ptr is NULL, no operation is performed. 205 | ## 206 | ## @param ptr Pointer to previously allocated memory. 207 | ## 208 | ## @return N/A 209 | ## 210 | proc k_free*(`ptr`: pointer) {.importc: "k_free", header: "kernel.h".} 211 | 212 | 213 | ## * 214 | ## @brief Allocate memory from heap, array style 215 | ## 216 | ## This routine provides traditional calloc() semantics. Memory is 217 | ## allocated from the heap memory pool and zeroed. 218 | ## 219 | ## @param nmemb Number of elements in the requested array 220 | ## @param size Size of each array element (in bytes). 221 | ## 222 | ## @return Address of the allocated memory if successful; otherwise NULL. 223 | ## 224 | proc k_calloc*(nmemb: csize_t; size: csize_t): pointer {.importc: "k_calloc", 225 | header: "kernel.h".} 226 | 227 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_memslab.nim: -------------------------------------------------------------------------------- 1 | 2 | import ../zconfs 3 | import ../zkernel_fixes 4 | import ../sys/zsys_heap 5 | import ../zsys_clock 6 | 7 | type 8 | k_mem_slab* {.importc: "k_mem_slab", header: "kernel.h", incompleteStruct, bycopy.} = object 9 | wait_q* {.importc: "wait_q".}: z_wait_q_t 10 | lock* {.importc: "lock".}: k_spinlock 11 | num_blocks* {.importc: "num_blocks".}: uint32 12 | block_size* {.importc: "block_size".}: csize_t 13 | buffer* {.importc: "buffer".}: cstring 14 | free_list* {.importc: "free_list".}: cstring 15 | num_used* {.importc: "num_used".}: uint32 16 | when CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION: 17 | max_used* {.importc: "max_used".}: uint32 18 | 19 | 20 | # proc Z_MEM_SLAB_INITIALIZER*(obj: untyped; slab_buffer: untyped; 21 | # slab_block_size: untyped; slab_num_blocks: untyped) {. 22 | # importc: "Z_MEM_SLAB_INITIALIZER", header: "kernel.h".} 23 | 24 | 25 | ## * 26 | ## INTERNAL_HIDDEN @endcond 27 | ## 28 | ## * 29 | ## @defgroup mem_slab_apis Memory Slab APIs 30 | ## @ingroup kernel_apis 31 | ## @{ 32 | ## 33 | ## * 34 | ## @brief Statically define and initialize a memory slab. 35 | ## 36 | ## The memory slab's buffer contains @a slab_num_blocks memory blocks 37 | ## that are @a slab_block_size bytes long. The buffer is aligned to a 38 | ## @a slab_align -byte boundary. To ensure that each memory block is similarly 39 | ## aligned to this boundary, @a slab_block_size must also be a multiple of 40 | ## @a slab_align. 41 | ## 42 | ## The memory slab can be accessed outside the module where it is defined 43 | ## using: 44 | ## 45 | ## @code extern struct k_mem_slab ; @endcode 46 | ## 47 | ## @param name Name of the memory slab. 48 | ## @param slab_block_size Size of each memory block (in bytes). 49 | ## @param slab_num_blocks Number memory blocks. 50 | ## @param slab_align Alignment of the memory slab's buffer (power of 2). 51 | ## 52 | # proc K_MEM_SLAB_DEFINE*(name: cminvtoken; slab_block_size: untyped; 53 | # slab_num_blocks: untyped; slab_align: untyped) {. 54 | # importc: "K_MEM_SLAB_DEFINE", header: "kernel.h".} 55 | 56 | 57 | ## * 58 | ## @brief Initialize a memory slab. 59 | ## 60 | ## Initializes a memory slab, prior to its first use. 61 | ## 62 | ## The memory slab's buffer contains @a slab_num_blocks memory blocks 63 | ## that are @a slab_block_size bytes long. The buffer must be aligned to an 64 | ## N-byte boundary matching a word boundary, where N is a power of 2 65 | ## (i.e. 4 on 32-bit systems, 8, 16, ...). 66 | ## To ensure that each memory block is similarly aligned to this boundary, 67 | ## @a slab_block_size must also be a multiple of N. 68 | ## 69 | ## @param slab Address of the memory slab. 70 | ## @param buffer Pointer to buffer used for the memory blocks. 71 | ## @param block_size Size of each memory block (in bytes). 72 | ## @param num_blocks Number of memory blocks. 73 | ## 74 | ## @retval 0 on success 75 | ## @retval -EINVAL invalid data supplied 76 | ## 77 | ## 78 | proc k_mem_slab_init*(slab: ptr k_mem_slab; buffer: pointer; block_size: csize_t; 79 | num_blocks: uint32): cint {.importc: "k_mem_slab_init", 80 | header: "kernel.h".} 81 | 82 | 83 | ## * 84 | ## @brief Allocate memory from a memory slab. 85 | ## 86 | ## This routine allocates a memory block from a memory slab. 87 | ## 88 | ## @note @a timeout must be set to K_NO_WAIT if called from ISR. 89 | ## @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT. 90 | ## 91 | ## @funcprops \isr_ok 92 | ## 93 | ## @param slab Address of the memory slab. 94 | ## @param mem Pointer to block address area. 95 | ## @param timeout Non-negative waiting period to wait for operation to complete. 96 | ## Use K_NO_WAIT to return without waiting, 97 | ## or K_FOREVER to wait as long as necessary. 98 | ## 99 | ## @retval 0 Memory allocated. The block address area pointed at by @a mem 100 | ## is set to the starting address of the memory block. 101 | ## @retval -ENOMEM Returned without waiting. 102 | ## @retval -EAGAIN Waiting period timed out. 103 | ## @retval -EINVAL Invalid data supplied 104 | ## 105 | proc k_mem_slab_alloc*(slab: ptr k_mem_slab; mem: ptr pointer; timeout: k_timeout_t): cint {. 106 | importc: "k_mem_slab_alloc", header: "kernel.h".} 107 | 108 | 109 | ## * 110 | ## @brief Free memory allocated from a memory slab. 111 | ## 112 | ## This routine releases a previously allocated memory block back to its 113 | ## associated memory slab. 114 | ## 115 | ## @param slab Address of the memory slab. 116 | ## @param mem Pointer to block address area (as set by k_mem_slab_alloc()). 117 | ## 118 | ## @return N/A 119 | ## 120 | proc k_mem_slab_free*(slab: ptr k_mem_slab; mem: ptr pointer) {. 121 | importc: "k_mem_slab_free", header: "kernel.h".} 122 | 123 | 124 | ## * 125 | ## @brief Get the number of used blocks in a memory slab. 126 | ## 127 | ## This routine gets the number of memory blocks that are currently 128 | ## allocated in @a slab. 129 | ## 130 | ## @param slab Address of the memory slab. 131 | ## 132 | ## @return Number of allocated memory blocks. 133 | ## 134 | proc k_mem_slab_num_used_get*(slab: ptr k_mem_slab): uint32 {. 135 | importc: "$1", header: "kernel.h".} 136 | 137 | ## * 138 | ## @brief Get the number of maximum used blocks so far in a memory slab. 139 | ## 140 | ## This routine gets the maximum number of memory blocks that were 141 | ## allocated in @a slab. 142 | ## 143 | ## @param slab Address of the memory slab. 144 | ## 145 | ## @return Maximum number of allocated memory blocks. 146 | ## 147 | proc k_mem_slab_max_used_get*(slab: ptr k_mem_slab): uint32 {. 148 | importc: "$1", header: "kernel.h".} 149 | 150 | ## * 151 | ## @brief Get the number of unused blocks in a memory slab. 152 | ## 153 | ## This routine gets the number of memory blocks that are currently 154 | ## unallocated in @a slab. 155 | ## 156 | ## @param slab Address of the memory slab. 157 | ## 158 | ## @return Number of unallocated memory blocks. 159 | ## 160 | proc k_mem_slab_num_free_get*(slab: ptr k_mem_slab): uint32 {. 161 | importc: "$1", header: "kernel.h".} 162 | 163 | ## * @} 164 | ## * 165 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_pipe.nim: -------------------------------------------------------------------------------- 1 | 2 | import ../zkernel_fixes 3 | import ../zsys_clock 4 | 5 | 6 | ## @defgroup pipe_apis Pipe APIs 7 | ## @ingroup kernel_apis 8 | ## @{ 9 | ## 10 | ## * Pipe Structure 11 | type 12 | INNER_C_STRUCT_kernel_2* {.importc: "no_name", header: "kernel.h", bycopy.} = object 13 | readers* {.importc: "readers".}: z_wait_q_t ## *< Reader wait queue 14 | writers* {.importc: "writers".}: z_wait_q_t ## *< Writer wait queue 15 | 16 | type 17 | k_pipe* {.importc: "struct k_pipe", header: "kernel.h", bycopy.} = object 18 | buffer* {.importc: "buffer".}: ptr cuchar ## *< Pipe buffer: may be NULL 19 | size* {.importc: "size".}: csize_t ## *< Buffer size 20 | bytes_used* {.importc: "bytes_used".}: csize_t ## *< # bytes used in buffer 21 | read_index* {.importc: "read_index".}: csize_t ## *< Where in buffer to read from 22 | write_index* {.importc: "write_index".}: csize_t ## *< Where in buffer to write 23 | lock* {.importc: "lock".}: k_spinlock ## *< Synchronization lock 24 | wait_q* {.importc: "wait_q".}: INNER_C_STRUCT_kernel_2 ## * Wait queue 25 | flags* {.importc: "flags".}: uint8 ## *< Flags 26 | 27 | ## * 28 | ## @cond INTERNAL_HIDDEN 29 | ## 30 | # var K_PIPE_FLAG_ALLOC* {.importc: "K_PIPE_FLAG_ALLOC", header: "kernel.h".}: int 31 | 32 | proc Z_PIPE_INITIALIZER*(obj: k_pipe; pipe_buffer: pointer; 33 | pipe_buffer_size: int) {. 34 | importc: "Z_PIPE_INITIALIZER", header: "kernel.h".} 35 | 36 | 37 | ## * 38 | ## INTERNAL_HIDDEN @endcond 39 | ## 40 | ## * 41 | ## @brief Statically define and initialize a pipe. 42 | ## 43 | ## The pipe can be accessed outside the module where it is defined using: 44 | ## 45 | ## @code extern struct k_pipe ; @endcode 46 | ## 47 | ## @param name Name of the pipe. 48 | ## @param pipe_buffer_size Size of the pipe's ring buffer (in bytes), 49 | ## or zero if no ring buffer is used. 50 | ## @param pipe_align Alignment of the pipe's ring buffer (power of 2). 51 | ## 52 | ## 53 | # proc K_PIPE_DEFINE*(name: cminvtoken; pipe_buffer_size: static[int]; pipe_align: static[int]) {. 54 | # importc: "K_PIPE_DEFINE", header: "kernel.h".} 55 | 56 | 57 | ## * 58 | ## @brief Initialize a pipe. 59 | ## 60 | ## This routine initializes a pipe object, prior to its first use. 61 | ## 62 | ## @param pipe Address of the pipe. 63 | ## @param buffer Address of the pipe's ring buffer, or NULL if no ring buffer 64 | ## is used. 65 | ## @param size Size of the pipe's ring buffer (in bytes), or zero if no ring 66 | ## buffer is used. 67 | ## 68 | ## @return N/A 69 | ## 70 | proc k_pipe_init*(pipe: ptr k_pipe; buffer: ptr cuchar; size: csize_t) {. 71 | importc: "k_pipe_init", header: "kernel.h".} 72 | 73 | 74 | ## * 75 | ## @brief Release a pipe's allocated buffer 76 | ## 77 | ## If a pipe object was given a dynamically allocated buffer via 78 | ## k_pipe_alloc_init(), this will free it. This function does nothing 79 | ## if the buffer wasn't dynamically allocated. 80 | ## 81 | ## @param pipe Address of the pipe. 82 | ## @retval 0 on success 83 | ## @retval -EAGAIN nothing to cleanup 84 | ## 85 | proc k_pipe_cleanup*(pipe: ptr k_pipe): cint {.importc: "k_pipe_cleanup", 86 | header: "kernel.h".} 87 | 88 | 89 | ## * 90 | ## @brief Initialize a pipe and allocate a buffer for it 91 | ## 92 | ## Storage for the buffer region will be allocated from the calling thread's 93 | ## resource pool. This memory will be released if k_pipe_cleanup() is called, 94 | ## or userspace is enabled and the pipe object loses all references to it. 95 | ## 96 | ## This function should only be called on uninitialized pipe objects. 97 | ## 98 | ## @param pipe Address of the pipe. 99 | ## @param size Size of the pipe's ring buffer (in bytes), or zero if no ring 100 | ## buffer is used. 101 | ## @retval 0 on success 102 | ## @retval -ENOMEM if memory couldn't be allocated 103 | ## 104 | proc k_pipe_alloc_init*(pipe: ptr k_pipe; size: csize_t): cint {.zsyscall, 105 | importc: "k_pipe_alloc_init", header: "kernel.h".} 106 | 107 | 108 | ## * 109 | ## @brief Write data to a pipe. 110 | ## 111 | ## This routine writes up to @a bytes_to_write bytes of data to @a pipe. 112 | ## 113 | ## @param pipe Address of the pipe. 114 | ## @param data Address of data to write. 115 | ## @param bytes_to_write Size of data (in bytes). 116 | ## @param bytes_written Address of area to hold the number of bytes written. 117 | ## @param min_xfer Minimum number of bytes to write. 118 | ## @param timeout Waiting period to wait for the data to be written, 119 | ## or one of the special values K_NO_WAIT and K_FOREVER. 120 | ## 121 | ## @retval 0 At least @a min_xfer bytes of data were written. 122 | ## @retval -EIO Returned without waiting; zero data bytes were written. 123 | ## @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer 124 | ## minus one data bytes were written. 125 | ## 126 | proc k_pipe_put*(pipe: ptr k_pipe; data: pointer; bytes_to_write: csize_t; 127 | bytes_written: ptr csize_t; min_xfer: csize_t; timeout: k_timeout_t): cint {. 128 | zsyscall, importc: "k_pipe_put", header: "kernel.h".} 129 | 130 | 131 | ## * 132 | ## @brief Read data from a pipe. 133 | ## 134 | ## This routine reads up to @a bytes_to_read bytes of data from @a pipe. 135 | ## 136 | ## @param pipe Address of the pipe. 137 | ## @param data Address to place the data read from pipe. 138 | ## @param bytes_to_read Maximum number of data bytes to read. 139 | ## @param bytes_read Address of area to hold the number of bytes read. 140 | ## @param min_xfer Minimum number of data bytes to read. 141 | ## @param timeout Waiting period to wait for the data to be read, 142 | ## or one of the special values K_NO_WAIT and K_FOREVER. 143 | ## 144 | ## @retval 0 At least @a min_xfer bytes of data were read. 145 | ## @retval -EINVAL invalid parameters supplied 146 | ## @retval -EIO Returned without waiting; zero data bytes were read. 147 | ## @retval -EAGAIN Waiting period timed out; between zero and @a min_xfer 148 | ## minus one data bytes were read. 149 | ## 150 | proc k_pipe_get*(pipe: ptr k_pipe; data: pointer; bytes_to_read: csize_t; 151 | bytes_read: ptr csize_t; min_xfer: csize_t; timeout: k_timeout_t): cint {. 152 | zsyscall, importc: "k_pipe_get", header: "kernel.h".} 153 | 154 | 155 | ## * 156 | ## @brief Query the number of bytes that may be read from @a pipe. 157 | ## 158 | ## @param pipe Address of the pipe. 159 | ## 160 | ## @retval a number n such that 0 <= n <= @ref k_pipe.size; the 161 | ## result is zero for unbuffered pipes. 162 | ## 163 | proc k_pipe_read_avail*(pipe: ptr k_pipe): csize_t {.zsyscall, 164 | importc: "k_pipe_read_avail", header: "kernel.h".} 165 | 166 | 167 | ## * 168 | ## @brief Query the number of bytes that may be written to @a pipe 169 | ## 170 | ## @param pipe Address of the pipe. 171 | ## 172 | ## @retval a number n such that 0 <= n <= @ref k_pipe.size; the 173 | ## result is zero for unbuffered pipes. 174 | ## 175 | proc k_pipe_write_avail*(pipe: ptr k_pipe): csize_t {.zsyscall, 176 | importc: "k_pipe_write_avail", header: "kernel.h".} 177 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_sem.nim: -------------------------------------------------------------------------------- 1 | import ../zkernel_fixes 2 | import ../zsys_clock 3 | 4 | type 5 | 6 | k_sem* {.importc: "struct k_sem", header: "kernel.h", incompleteStruct, bycopy.} = object 7 | wait_q* {.importc: "wait_q".}: z_wait_q_t 8 | count* {.importc: "count".}: cuint 9 | limit* {.importc: "limit".}: cuint 10 | poll_events* {.importc: "poll_events".}: sys_dlist_t ## _POLL_EVENT; 11 | 12 | 13 | ## * 14 | ## @cond INTERNAL_HIDDEN 15 | ## 16 | 17 | proc Z_SEM_INITIALIZER*(obj: k_sem; initial_count: static[int]; count_limit: static[int]) {. 18 | importc: "Z_SEM_INITIALIZER", header: "kernel.h".} 19 | 20 | 21 | ## * 22 | ## INTERNAL_HIDDEN @endcond 23 | ## 24 | ## * 25 | 26 | ## @defgroup semaphore_apis Semaphore APIs 27 | ## @ingroup kernel_apis 28 | ## @{ 29 | ## 30 | ## * 31 | ## @brief Maximum limit value allowed for a semaphore. 32 | ## 33 | ## This is intended for use when a semaphore does not have 34 | ## an explicit maximum limit, and instead is just used for 35 | ## counting purposes. 36 | ## 37 | ## 38 | var K_SEM_MAX_LIMIT* {.importc: "K_SEM_MAX_LIMIT", header: "kernel.h".}: int 39 | 40 | 41 | ## * 42 | ## @brief Initialize a semaphore. 43 | ## 44 | ## This routine initializes a semaphore object, prior to its first use. 45 | ## 46 | ## @param sem Address of the semaphore. 47 | ## @param initial_count Initial semaphore count. 48 | ## @param limit Maximum permitted semaphore count. 49 | ## 50 | ## @see K_SEM_MAX_LIMIT 51 | ## 52 | ## @retval 0 Semaphore created successfully 53 | ## @retval -EINVAL Invalid values 54 | ## 55 | ## 56 | proc k_sem_init*(sem: ptr k_sem; initial_count: cuint; limit: cuint): cint {.zsyscall, 57 | importc: "k_sem_init", header: "kernel.h".} 58 | 59 | 60 | ## * 61 | ## @brief Take a semaphore. 62 | ## 63 | ## This routine takes @a sem. 64 | ## 65 | ## @note @a timeout must be set to K_NO_WAIT if called from ISR. 66 | ## 67 | ## @funcprops \isr_ok 68 | ## 69 | ## @param sem Address of the semaphore. 70 | ## @param timeout Waiting period to take the semaphore, 71 | ## or one of the special values K_NO_WAIT and K_FOREVER. 72 | ## 73 | ## @retval 0 Semaphore taken. 74 | ## @retval -EBUSY Returned without waiting. 75 | ## @retval -EAGAIN Waiting period timed out, 76 | ## or the semaphore was reset during the waiting period. 77 | ## 78 | proc k_sem_take*(sem: ptr k_sem; timeout: k_timeout_t): cint {.zsyscall, 79 | importc: "k_sem_take", header: "kernel.h".} 80 | 81 | 82 | ## * 83 | ## @brief Give a semaphore. 84 | ## 85 | ## This routine gives @a sem, unless the semaphore is already at its maximum 86 | ## permitted count. 87 | ## 88 | ## @funcprops \isr_ok 89 | ## 90 | ## @param sem Address of the semaphore. 91 | ## 92 | ## @return N/A 93 | ## 94 | proc k_sem_give*(sem: ptr k_sem) {.zsyscall, importc: "k_sem_give", header: "kernel.h".} 95 | 96 | 97 | ## * 98 | ## @brief Resets a semaphore's count to zero. 99 | ## 100 | ## This routine sets the count of @a sem to zero. 101 | ## Any outstanding semaphore takes will be aborted 102 | ## with -EAGAIN. 103 | ## 104 | ## @param sem Address of the semaphore. 105 | ## 106 | ## @return N/A 107 | ## 108 | proc k_sem_reset*(sem: ptr k_sem) {.zsyscall, importc: "k_sem_reset", 109 | header: "kernel.h".} 110 | 111 | 112 | ## * 113 | ## @brief Get a semaphore's count. 114 | ## 115 | ## This routine returns the current count of @a sem. 116 | ## 117 | ## @param sem Address of the semaphore. 118 | ## 119 | ## @return Current semaphore count. 120 | ## 121 | proc k_sem_count_get*(sem: ptr k_sem): cuint {.zsyscall, importc: "k_sem_count_get", 122 | header: "kernel.h".} 123 | 124 | 125 | ## * 126 | ## @internal 127 | ## 128 | proc z_impl_k_sem_count_get*(sem: ptr k_sem): cuint {. 129 | importc: "$1", header: "kernel.h".} 130 | 131 | ## * 132 | ## @brief Statically define and initialize a semaphore. 133 | ## 134 | ## The semaphore can be accessed outside the module where it is defined using: 135 | ## 136 | ## @code extern struct k_sem ; @endcode 137 | ## 138 | ## @param name Name of the semaphore. 139 | ## @param initial_count Initial semaphore count. 140 | ## @param count_limit Maximum permitted semaphore count. 141 | ## 142 | proc K_SEM_DEFINE*(name: cminvtoken; initial_count: static[int]; count_limit: static[int]) {. 143 | importc: "K_SEM_DEFINE", header: "kernel.h".} 144 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/kernel/zk_stack.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import ../zkernel_fixes 4 | import ../zsys_clock 5 | 6 | 7 | ## * @} 8 | ## * 9 | ## @cond INTERNAL_HIDDEN 10 | ## 11 | # var K_STACK_FLAG_ALLOC* {.importc: "K_STACK_FLAG_ALLOC", header: "kernel.h".}: int 12 | 13 | type 14 | stack_data_t* = pointer 15 | 16 | k_stack* {.importc: "struct k_stack", header: "kernel.h", bycopy.} = object 17 | wait_q* {.importc: "wait_q".}: z_wait_q_t 18 | lock* {.importc: "lock".}: k_spinlock 19 | base* {.importc: "base".}: ptr stack_data_t 20 | next* {.importc: "next".}: ptr stack_data_t 21 | top* {.importc: "top".}: ptr stack_data_t 22 | flags* {.importc: "flags".}: uint8 23 | 24 | # proc Z_STACK_INITIALIZER*(obj: untyped; stack_buffer: untyped; 25 | # stack_num_entries: untyped) {. 26 | # importc: "Z_STACK_INITIALIZER", header: "kernel.h".} 27 | 28 | 29 | ## * 30 | ## INTERNAL_HIDDEN @endcond 31 | ## 32 | ## * 33 | ## @defgroup stack_apis Stack APIs 34 | ## @ingroup kernel_apis 35 | ## @{ 36 | ## 37 | ## * 38 | ## @brief Initialize a stack. 39 | ## 40 | ## This routine initializes a stack object, prior to its first use. 41 | ## 42 | ## @param stack Address of the stack. 43 | ## @param buffer Address of array used to hold stacked values. 44 | ## @param num_entries Maximum number of values that can be stacked. 45 | ## 46 | ## @return N/A 47 | ## 48 | proc k_stack_init*(stack: ptr k_stack; buffer: ptr stack_data_t; 49 | num_entries: uint32) {.importc: "k_stack_init", 50 | header: "kernel.h".} 51 | 52 | 53 | ## * 54 | ## @brief Initialize a stack. 55 | ## 56 | ## This routine initializes a stack object, prior to its first use. Internal 57 | ## buffers will be allocated from the calling thread's resource pool. 58 | ## This memory will be released if k_stack_cleanup() is called, or 59 | ## userspace is enabled and the stack object loses all references to it. 60 | ## 61 | ## @param stack Address of the stack. 62 | ## @param num_entries Maximum number of values that can be stacked. 63 | ## 64 | ## @return -ENOMEM if memory couldn't be allocated 65 | ## 66 | proc k_stack_alloc_init*(stack: ptr k_stack; num_entries: uint32): int32 {. 67 | zsyscall, importc: "k_stack_alloc_init", header: "kernel.h".} 68 | 69 | 70 | ## * 71 | ## @brief Release a stack's allocated buffer 72 | ## 73 | ## If a stack object was given a dynamically allocated buffer via 74 | ## k_stack_alloc_init(), this will free it. This function does nothing 75 | ## if the buffer wasn't dynamically allocated. 76 | ## 77 | ## @param stack Address of the stack. 78 | ## @retval 0 on success 79 | ## @retval -EAGAIN when object is still in use 80 | ## 81 | proc k_stack_cleanup*(stack: ptr k_stack): cint {.importc: "k_stack_cleanup", 82 | header: "kernel.h".} 83 | 84 | 85 | ## * 86 | ## @brief Push an element onto a stack. 87 | ## 88 | ## This routine adds a stack_data_t value @a data to @a stack. 89 | ## 90 | ## @funcprops \isr_ok 91 | ## 92 | ## @param stack Address of the stack. 93 | ## @param data Value to push onto the stack. 94 | ## 95 | ## @retval 0 on success 96 | ## @retval -ENOMEM if stack is full 97 | ## 98 | proc k_stack_push*(stack: ptr k_stack; data: stack_data_t): cint {.zsyscall, 99 | importc: "k_stack_push", header: "kernel.h".} 100 | 101 | 102 | ## * 103 | ## @brief Pop an element from a stack. 104 | ## 105 | ## This routine removes a stack_data_t value from @a stack in a "last in, 106 | ## first out" manner and stores the value in @a data. 107 | ## 108 | ## @note @a timeout must be set to K_NO_WAIT if called from ISR. 109 | ## 110 | ## @funcprops \isr_ok 111 | ## 112 | ## @param stack Address of the stack. 113 | ## @param data Address of area to hold the value popped from the stack. 114 | ## @param timeout Waiting period to obtain a value, 115 | ## or one of the special values K_NO_WAIT and 116 | ## K_FOREVER. 117 | ## 118 | ## @retval 0 Element popped from stack. 119 | ## @retval -EBUSY Returned without waiting. 120 | ## @retval -EAGAIN Waiting period timed out. 121 | ## 122 | proc k_stack_pop*(stack: ptr k_stack; data: ptr stack_data_t; timeout: k_timeout_t): cint {. 123 | zsyscall, importc: "k_stack_pop", header: "kernel.h".} 124 | 125 | 126 | ## * 127 | ## @brief Statically define and initialize a stack 128 | ## 129 | ## The stack can be accessed outside the module where it is defined using: 130 | ## 131 | ## @code extern struct k_stack ; @endcode 132 | ## 133 | ## @param name Name of the stack. 134 | ## @param stack_num_entries Maximum number of values that can be stacked. 135 | ## 136 | proc K_STACK_DEFINE*(name: cminvtoken; stack_num_entries: static[int]) {. 137 | importc: "K_STACK_DEFINE", header: "kernel.h".} 138 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/net/znet_config.nim: -------------------------------------------------------------------------------- 1 | ## * @file 2 | ## @brief Routines for network subsystem initialization. 3 | ## 4 | ## 5 | ## Copyright (c) 2017 Intel Corporation 6 | ## 7 | ## SPDX-License-Identifier: Apache-2.0 8 | ## 9 | 10 | ## * 11 | ## @brief Network configuration library 12 | ## @defgroup net_config Network Configuration Library 13 | ## @ingroup networking 14 | ## @{ 15 | ## 16 | ## Flags that tell what kind of functionality is needed by the client. 17 | ## * 18 | ## @brief Application needs routers to be set so that connectivity to remote 19 | ## network is possible. For IPv6 networks, this means that the device should 20 | ## receive IPv6 router advertisement message before continuing. 21 | ## 22 | 23 | import ../zdevice 24 | import znet_if 25 | 26 | const hdr = "" 27 | 28 | const 29 | NET_CONFIG_NEED_ROUTER* = 0x00000001 30 | 31 | ## * 32 | ## @brief Application needs IPv6 subsystem configured and initialized. 33 | ## Typically this means that the device has IPv6 address set. 34 | ## 35 | 36 | const 37 | NET_CONFIG_NEED_IPV6* = 0x00000002 38 | 39 | ## * 40 | ## @brief Application needs IPv4 subsystem configured and initialized. 41 | ## Typically this means that the device has IPv4 address set. 42 | ## 43 | 44 | const 45 | NET_CONFIG_NEED_IPV4* = 0x00000004 46 | 47 | ## * 48 | ## @brief Initialize this network application. 49 | ## 50 | ## @details This will call net_config_init_by_iface() with NULL network 51 | ## interface. 52 | ## 53 | ## @param app_info String describing this application. 54 | ## @param flags Flags related to services needed by the client. 55 | ## @param timeout How long to wait the network setup before continuing 56 | ## the startup. 57 | ## 58 | ## @return 0 if ok, <0 if error. 59 | ## 60 | 61 | proc net_config_init*(app_info: cstring; flags: uint32; timeout: int32): cint {. 62 | importc: "net_config_init", header: hdr.} 63 | 64 | ## * 65 | ## @brief Initialize this network application using a specific network 66 | ## interface. 67 | ## 68 | ## @details If network interface is set to NULL, then the default one 69 | ## is used in the configuration. 70 | ## 71 | ## @param iface Initialize networking using this network interface. 72 | ## @param app_info String describing this application. 73 | ## @param flags Flags related to services needed by the client. 74 | ## @param timeout How long to wait the network setup before continuing 75 | ## the startup. 76 | ## 77 | ## @return 0 if ok, <0 if error. 78 | ## 79 | 80 | proc net_config_init_by_iface*(iface: ptr net_if; app_info: cstring; flags: uint32; 81 | timeout: int32): cint {. 82 | importc: "net_config_init_by_iface", header: hdr.} 83 | 84 | ## * 85 | ## @brief Initialize this network application. 86 | ## 87 | ## @details If CONFIG_NET_CONFIG_AUTO_INIT is set, then this function is called 88 | ## automatically when the device boots. If that is not desired, unset 89 | ## the config option and call the function manually when the 90 | ## application starts. 91 | ## 92 | ## @param dev Network device to use. The function will figure out what 93 | ## network interface to use based on the device. If the device is NULL, 94 | ## then default network interface is used by the function. 95 | ## @param app_info String describing this application. 96 | ## 97 | ## @return 0 if ok, <0 if error. 98 | ## 99 | 100 | proc net_config_init_app*(dev: ptr device; app_info: cstring): cint {. 101 | importc: "net_config_init_app", header: hdr.} 102 | 103 | ## * 104 | ## @} 105 | ## 106 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/net/znet_core.nim: -------------------------------------------------------------------------------- 1 | ## * @file 2 | ## @brief Network core definitions 3 | ## 4 | ## Definitions for networking support. 5 | ## 6 | ## 7 | ## Copyright (c) 2015 Intel Corporation 8 | ## 9 | ## SPDX-License-Identifier: Apache-2.0 10 | ## 11 | 12 | ## * 13 | ## @brief Networking 14 | ## @defgroup networking Networking 15 | ## @{ 16 | ## @} 17 | ## 18 | ## * 19 | ## @brief Network core library 20 | ## @defgroup net_core Network Core Library 21 | ## @ingroup networking 22 | ## @{ 23 | ## 24 | ## * @cond INTERNAL_HIDDEN 25 | ## Network subsystem logging helpers 26 | 27 | type 28 | net_if_alias* {.incompleteStruct, bycopy.} = distinct object 29 | net_pkt_alias* {.incompleteStruct, bycopy.} = distinct object 30 | net_offload_alias* {.incompleteStruct, bycopy.} = distinct object 31 | 32 | net_nbr_alias* {.incompleteStruct, bycopy.} = distinct object 33 | 34 | net_verdict* {.size: sizeof(cint).} = enum 35 | NET_OK, ##\ 36 | ## * Packet has been taken care of. 37 | NET_CONTINUE, ##\ 38 | ## * Packet has not been touched, other part should decide about its 39 | ## fate. 40 | NET_DROP ##\ 41 | ## * Packet must be dropped. 42 | 43 | 44 | ## * 45 | ## @brief Called by lower network stack or network device driver when 46 | ## a network packet has been received. The function will push the packet up in 47 | ## the network stack for further processing. 48 | ## 49 | ## @param iface Network interface where the packet was received. 50 | ## @param pkt Network packet data. 51 | ## 52 | ## @return 0 if ok, <0 if error. 53 | ## 54 | 55 | # TODO: FIXME 56 | # proc net_recv_data*(iface: ptr net_if; pkt: ptr net_pkt): cint {. 57 | # importc: "net_recv_data", header: "net_core.h".} 58 | 59 | ## * 60 | ## @brief Send data to network. 61 | ## 62 | ## @details Send data to network. This should not be used normally by 63 | ## applications as it requires that the network packet is properly 64 | ## constructed. 65 | ## 66 | ## @param pkt Network packet. 67 | ## 68 | ## @return 0 if ok, <0 if error. If <0 is returned, then the caller needs 69 | ## to unref the pkt in order to avoid memory leak. 70 | ## 71 | 72 | # TODO: FIXME 73 | # proc net_send_data*(pkt: ptr net_pkt): cint {.importc: "net_send_data", 74 | # header: "net_core.h".} 75 | 76 | var NET_TC_TX_COUNT* {.importc: "NET_TC_TX_COUNT", header: "net_core.h".}: cint 77 | var NET_TC_RX_COUNT* {.importc: "NET_TC_RX_COUNT", header: "net_core.h".}: cint 78 | var NET_TC_COUNT* {.importc: "NET_TC_COUNT", header: "net_core.h".}: cint 79 | 80 | ## @endcond 81 | ## * 82 | ## @} 83 | ## 84 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/net/znet_l2.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2016 Intel Corporation. 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | ## * 7 | ## @file 8 | ## @brief Public API for network L2 interface 9 | ## 10 | 11 | ## * 12 | ## @brief Network Layer 2 abstraction layer 13 | ## @defgroup net_l2 Network L2 Abstraction Layer 14 | ## @ingroup networking 15 | ## @{ 16 | ## 17 | 18 | import ../wrapper_utils 19 | import ../zdevice 20 | import znet_core 21 | 22 | const hdr = "" 23 | 24 | type 25 | net_l2_flags* {.size: sizeof(cint).} = enum ## * IP multicast supported 26 | NET_L2_MULTICAST = BIT(0), ## * Do not joint solicited node multicast group 27 | NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE = BIT(1), ## * Is promiscuous mode supported 28 | NET_L2_PROMISC_MODE = BIT(2), ## * Is this L2 point-to-point with tunneling so no need to have 29 | ## IP address etc to network interface. 30 | ## 31 | NET_L2_POINT_TO_POINT = BIT(3) 32 | 33 | ## * 34 | ## @brief Network L2 structure 35 | ## 36 | ## Used to provide an interface to lower network stack. 37 | ## 38 | 39 | type 40 | net_l2* {.importc: "struct net_l2", header: hdr, bycopy.} = object 41 | 42 | recv* {.importc: "recv".}: proc (iface: ptr net_if_alias; pkt: ptr net_pkt_alias): net_verdict {.cdecl.} ##\ 43 | ## This function is used by net core to get iface's L2 layer parsing 44 | ## what's relevant to itself. 45 | ## 46 | send* {.importc: "send".}: proc (iface: ptr net_if_alias; pkt: ptr net_pkt_alias): cint {.cdecl.} ##\ 47 | ## * 48 | ## This function is used by net core to push a packet to lower layer 49 | ## (interface's L2), which in turn might work on the packet relevantly. 50 | ## (adding proper header etc...) 51 | ## Returns a negative error code, or the number of bytes sent otherwise. 52 | ## 53 | enable* {.importc: "enable".}: proc (iface: ptr net_if_alias; state: bool): cint {.cdecl.} ##\ 54 | ## This function is used to enable/disable traffic over a network 55 | ## interface. The function returns <0 if error and >=0 if no error. 56 | ## 57 | get_flags* {.importc: "get_flags".}: proc (iface: ptr net_if_alias): net_l2_flags {.cdecl.} ## *\ 58 | ## Return L2 flags for the network interface. 59 | ## 60 | 61 | net_l2_send_t* = proc (dev: ptr device; pkt: ptr net_pkt_alias): cint {.cdecl.} 62 | 63 | ## /** @cond INTERNAL_HIDDEN */ 64 | ## #define NET_L2_GET_NAME(_name) _net_l2_##_name 65 | ## #define NET_L2_DECLARE_PUBLIC(_name) \ 66 | ## extern const struct net_l2 NET_L2_GET_NAME(_name) 67 | ## #define NET_L2_GET_CTX_TYPE(_name) _name##_CTX_TYPE 68 | ## #ifdef CONFIG_NET_L2_VIRTUAL 69 | ## #define VIRTUAL_L2 VIRTUAL 70 | ## NET_L2_DECLARE_PUBLIC(VIRTUAL_L2); 71 | ## #endif /* CONFIG_NET_L2_DUMMY */ 72 | ## #ifdef CONFIG_NET_L2_DUMMY 73 | ## #define DUMMY_L2 DUMMY 74 | ## #define DUMMY_L2_CTX_TYPE void* 75 | ## NET_L2_DECLARE_PUBLIC(DUMMY_L2); 76 | ## #endif /* CONFIG_NET_L2_DUMMY */ 77 | ## #ifdef CONFIG_NET_L2_ETHERNET 78 | ## #define ETHERNET_L2 ETHERNET 79 | ## NET_L2_DECLARE_PUBLIC(ETHERNET_L2); 80 | ## #endif /* CONFIG_NET_L2_ETHERNET */ 81 | ## #ifdef CONFIG_NET_L2_PPP 82 | ## #define PPP_L2 PPP 83 | ## NET_L2_DECLARE_PUBLIC(PPP_L2); 84 | ## #endif /* CONFIG_NET_L2_PPP */ 85 | ## #ifdef CONFIG_NET_L2_IEEE802154 86 | ## #define IEEE802154_L2 IEEE802154 87 | ## NET_L2_DECLARE_PUBLIC(IEEE802154_L2); 88 | ## #endif /* CONFIG_NET_L2_IEEE802154 */ 89 | ## #ifdef CONFIG_NET_L2_BT 90 | ## #define BLUETOOTH_L2 BLUETOOTH 91 | ## #define BLUETOOTH_L2_CTX_TYPE void* 92 | ## NET_L2_DECLARE_PUBLIC(BLUETOOTH_L2); 93 | ## #endif /* CONFIG_NET_L2_BT */ 94 | ## #ifdef CONFIG_NET_L2_OPENTHREAD 95 | ## #define OPENTHREAD_L2 OPENTHREAD 96 | ## NET_L2_DECLARE_PUBLIC(OPENTHREAD_L2); 97 | ## #endif /* CONFIG_NET_L2_OPENTHREAD */ 98 | ## #ifdef CONFIG_NET_L2_CANBUS_RAW 99 | ## #define CANBUS_RAW_L2 CANBUS_RAW 100 | ## #define CANBUS_RAW_L2_CTX_TYPE void* 101 | ## NET_L2_DECLARE_PUBLIC(CANBUS_RAW_L2); 102 | ## #endif /* CONFIG_NET_L2_CANBUS_RAW */ 103 | ## #ifdef CONFIG_NET_L2_CANBUS 104 | ## #define CANBUS_L2 CANBUS 105 | ## NET_L2_DECLARE_PUBLIC(CANBUS_L2); 106 | ## #endif /* CONFIG_NET_L2_CANBUS */ 107 | 108 | # proc NET_L2_INIT*(name: untyped; _recv_fn: untyped; _send_fn: untyped; 109 | # _enable_fn: untyped; _get_flags_fn: untyped) {. 110 | # importc: "NET_L2_INIT", header: hdr.} 111 | # proc NET_L2_GET_DATA*(name: untyped; sfx: untyped) {.importc: "NET_L2_GET_DATA", 112 | # header: hdr.} 113 | # proc NET_L2_DATA_INIT*(name: untyped; sfx: untyped; ctx_type: untyped) {. 114 | # importc: "NET_L2_DATA_INIT", header: hdr.} 115 | 116 | proc net_l2_send*(send_fn: net_l2_send_t, 117 | dev: ptr device, 118 | iface: ptr net_if_alias, 119 | pkt: ptr net_pkt_alias 120 | ): cint {.importc: "$1", header: "".} 121 | 122 | ## * @endcond 123 | ## * 124 | ## @} 125 | ## 126 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/net/znet_linkaddr.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2016 Intel Corporation. 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | ## * 7 | ## @file 8 | ## @brief Public API for network link address 9 | ## 10 | 11 | ## * 12 | ## @brief Network link address library 13 | ## @defgroup net_linkaddr Network Link Address Library 14 | ## @ingroup networking 15 | ## @{ 16 | ## 17 | ## * Maximum length of the link address 18 | 19 | import ../zconfs 20 | 21 | const hdr = "#include \n#include " 22 | 23 | const 24 | NET_LINK_ADDR_MAX_LENGTH* = 25 | when CONFIG_NET_L2_IEEE802154: 26 | 8 27 | elif CONFIG_NET_L2_PPP: 28 | 8 29 | else: 30 | 6 31 | 32 | ## * 33 | ## Type of the link address. This indicates the network technology that this 34 | ## address is used in. Note that in order to save space we store the value 35 | ## into a uint8_t variable, so please do not introduce any values > 255 in 36 | ## this enum. 37 | ## 38 | ## packed 39 | 40 | type 41 | net_link_type* {.size: sizeof(uint8).} = enum ## * Unknown link address type. 42 | NET_LINK_UNKNOWN = 0, ## * IEEE 802.15.4 link address. 43 | NET_LINK_IEEE802154, ## * Bluetooth IPSP link address. 44 | NET_LINK_BLUETOOTH, ## * Ethernet link address. 45 | NET_LINK_ETHERNET, ## * Dummy link address. Used in testing apps and loopback support. 46 | NET_LINK_DUMMY, ## * CANBUS link address. 47 | NET_LINK_CANBUS_RAW, ## * 6loCAN link address. 48 | NET_LINK_CANBUS 49 | 50 | 51 | ## * 52 | ## @brief Hardware link address structure 53 | ## 54 | ## Used to hold the link address information 55 | ## 56 | 57 | type 58 | net_linkaddr* {.importc: "struct net_linkaddr", header: hdr, bycopy.} = object 59 | caddr* {.importc: "addr".}: ptr uint8 ## * The array of byte representing the address 60 | ## * Length of that address array 61 | len* {.importc: "len".}: uint8 ## * What kind of address is this for 62 | ctype* {.importc: "type".}: uint8 63 | 64 | 65 | ## * 66 | ## @brief Hardware link address structure 67 | ## 68 | ## Used to hold the link address information. This variant is needed 69 | ## when we have to store the link layer address. 70 | ## 71 | ## Note that you cannot cast this to net_linkaddr as uint8_t * is 72 | ## handled differently than uint8_t addr[] and the fields are purposely 73 | ## in different order. 74 | ## 75 | 76 | type 77 | net_linkaddr_storage* {.importc: "struct net_linkaddr_storage", 78 | header: hdr, bycopy.} = object 79 | ctype* {.importc: "type".}: uint8 ## * What kind of address is this for 80 | ## * The real length of the ll address. 81 | len* {.importc: "len".}: uint8 ## * The array of bytes representing the address 82 | caddr* {.importc: "addr".}: array[NET_LINK_ADDR_MAX_LENGTH, uint8] 83 | 84 | 85 | ## * 86 | ## @brief Compare two link layer addresses. 87 | ## 88 | ## @param lladdr1 Pointer to a link layer address 89 | ## @param lladdr2 Pointer to a link layer address 90 | ## 91 | ## @return True if the addresses are the same, false otherwise. 92 | ## 93 | 94 | proc net_linkaddr_cmp*(lladdr1: ptr net_linkaddr; lladdr2: ptr net_linkaddr): bool {. 95 | importc: "$1", header: hdr.} 96 | 97 | ## * 98 | ## 99 | ## @brief Set the member data of a link layer address storage structure. 100 | ## 101 | ## @param lladdr_store The link address storage structure to change. 102 | ## @param new_addr Array of bytes containing the link address. 103 | ## @param new_len Length of the link address array. 104 | ## This value should always be <= NET_LINK_ADDR_MAX_LENGTH. 105 | ## 106 | 107 | proc net_linkaddr_set*(lladdr_store: ptr net_linkaddr_storage; new_addr: ptr uint8; 108 | new_len: uint8): cint {.importc: "$1", header: hdr.} 109 | 110 | ## * 111 | ## @} 112 | ## 113 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/net/znet_timeout.nim: -------------------------------------------------------------------------------- 1 | ## * @file 2 | ## @brief Network timer with wrap around 3 | ## 4 | ## Timer that runs longer than about 49 days needs to calculate wraps. 5 | ## 6 | ## 7 | ## Copyright (c) 2018 Intel Corporation 8 | ## Copyright (c) 2020 Nordic Semiconductor ASA 9 | ## 10 | ## SPDX-License-Identifier: Apache-2.0 11 | ## 12 | 13 | ## * 14 | ## @brief Network long timeout primitives and helpers 15 | ## @defgroup net_timeout Network long timeout primitives and helpers 16 | ## @ingroup networking 17 | ## @{ 18 | ## 19 | 20 | ## * @brief Divisor used to support ms resolution timeouts. 21 | ## 22 | ## Because delays are processed in work queues which are not invoked 23 | ## synchronously with clock changes we need to be able to detect timeouts 24 | ## after they occur, which requires comparing "deadline" to "now" with enough 25 | ## "slop" to handle any observable latency due to "now" advancing past 26 | ## "deadline". 27 | ## 28 | ## The simplest solution is to use the native conversion of the well-defined 29 | ## 32-bit unsigned difference to a 32-bit signed difference, which caps the 30 | ## maximum delay at INT32_MAX. This is compatible with the standard mechanism 31 | ## for detecting completion of deadlines that do not overflow their 32 | ## representation. 33 | ## 34 | 35 | import ../zkernel_fixes 36 | 37 | const hdr = "" 38 | 39 | const 40 | NET_TIMEOUT_MAX_VALUE* = high(int32) 41 | 42 | 43 | type 44 | net_timeout* {.importc: "struct net_timeout", header: hdr, bycopy.} = object 45 | ## * Generic struct for handling network timeouts. 46 | ## 47 | ## Except for the linking node, all access to state from these objects must go 48 | ## through the defined API. 49 | ## 50 | node* {.importc: "node".}: sys_snode_t ##\ 51 | ## * Used to link multiple timeouts that share a common timer infrastructure. 52 | ## 53 | ## For examples a set of related timers may use a single delayed work 54 | ## structure, which is always scheduled at the shortest time to a 55 | ## timeout event. 56 | ## 57 | timer_start* {.importc: "timer_start".}: uint32 ##\ 58 | ## Time at which the timer was last set. 59 | ## 60 | ## This usually corresponds to the low 32 bits of k_uptime_get(). 61 | timer_timeout* {.importc: "timer_timeout".}: uint32 ##\ 62 | ## Portion of remaining timeout that does not exceed 63 | ## NET_TIMEOUT_MAX_VALUE. 64 | ## 65 | ## This value is updated in parallel with timer_start and wrap_counter 66 | ## by net_timeout_evaluate(). 67 | ## 68 | wrap_counter* {.importc: "wrap_counter".}: uint32 ##\ 69 | ## Timer wrap count. 70 | ## 71 | ## This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that 72 | ## have yet to pass. It is also updated along with timer_start and 73 | ## wrap_counter by net_timeout_evaluate(). 74 | ## 75 | 76 | 77 | ## * @brief Configure a network timeout structure. 78 | ## 79 | ## @param timeout a pointer to the timeout state. 80 | ## 81 | ## @param lifetime the duration of the timeout in seconds. 82 | ## 83 | ## @param now the time at which the timeout started counting down, in 84 | ## milliseconds. This is generally a captured value of k_uptime_get_32(). 85 | ## 86 | 87 | proc net_timeout_set*(timeout: ptr net_timeout; lifetime: uint32; now: uint32) {. 88 | importc: "net_timeout_set", header: hdr.} 89 | 90 | 91 | ## * @brief Return the 64-bit system time at which the timeout will complete. 92 | ## 93 | ## @note Correct behavior requires invocation of net_timeout_evaluate() at its 94 | ## specified intervals. 95 | ## 96 | ## @param timeout state a pointer to the timeout state, initialized by 97 | ## net_timeout_set() and maintained by net_timeout_evaluate(). 98 | ## 99 | ## @param now the full-precision value of k_uptime_get() relative to which the 100 | ## deadline will be calculated. 101 | ## 102 | ## @return the value of k_uptime_get() at which the timeout will expire. 103 | ## 104 | 105 | proc net_timeout_deadline*(timeout: ptr net_timeout; now: int64): int64 {. 106 | importc: "net_timeout_deadline", header: hdr.} 107 | 108 | 109 | ## * @brief Calculate the remaining time to the timeout in whole seconds. 110 | ## 111 | ## @note This function rounds the remaining time down, i.e. if the timeout 112 | ## will occur in 3500 milliseconds the value 3 will be returned. 113 | ## 114 | ## @note Correct behavior requires invocation of net_timeout_evaluate() at its 115 | ## specified intervals. 116 | ## 117 | ## @param timeout a pointer to the timeout state 118 | ## 119 | ## @param now the time relative to which the estimate of remaining time should 120 | ## be calculated. This should be recently captured value from 121 | ## k_uptime_get_32(). 122 | ## 123 | ## @retval 0 if the timeout has completed. 124 | ## @retval positive the remaining duration of the timeout, in seconds. 125 | ## 126 | 127 | proc net_timeout_remaining*(timeout: ptr net_timeout; now: uint32): uint32 {. 128 | importc: "net_timeout_remaining", header: hdr.} 129 | 130 | 131 | ## * @brief Update state to reflect elapsed time and get new delay. 132 | ## 133 | ## This function must be invoked periodically to (1) apply the effect of 134 | ## elapsed time on what remains of a total delay that exceeded the maximum 135 | ## representable delay, and (2) determine that either the timeout has 136 | ## completed or that the infrastructure must wait a certain period before 137 | ## checking again for completion. 138 | ## 139 | ## @param timeout a pointer to the timeout state 140 | ## 141 | ## @param now the time relative to which the estimate of remaining time should 142 | ## be calculated. This should be recently captured value from 143 | ## k_uptime_get_32(). 144 | ## 145 | ## @retval 0 if the timeout has completed 146 | ## @retval positive the maximum delay until the state of this timeout should 147 | ## be re-evaluated, in milliseconds. 148 | ## 149 | 150 | proc net_timeout_evaluate*(timeout: ptr net_timeout; now: uint32): uint32 {. 151 | importc: "net_timeout_evaluate", header: hdr.} 152 | 153 | 154 | ## * 155 | ## @} 156 | ## 157 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/wrapper_utils.nim: -------------------------------------------------------------------------------- 1 | import zcmtoken 2 | export zcmtoken 3 | 4 | template BIT*(n: untyped): untyped = 5 | 1 shl n 6 | 7 | template NephyrDefineDistinctFlag*(T: untyped, V: typedesc) = 8 | ## defines a distinct 'flag' type, useful for uint32 options types 9 | type 10 | T* = distinct V 11 | proc `or` *(x, y: T): T {.borrow.} 12 | 13 | type 14 | ## single linked list node, used in some api's 15 | 16 | k_poll_signal* {.importc: "k_poll_signal", header: "kernel.h", bycopy.} = object ##\ 17 | ## TODO: import kernel.h 18 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zatomic.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 1997-2015, Wind River Systems, Inc. 3 | ## Copyright (c) 2021 Intel Corporation 4 | ## 5 | ## SPDX-License-Identifier: Apache-2.0 6 | ## 7 | 8 | type 9 | atomic_t* = cint 10 | atomic_ptr_t* = distinct pointer 11 | atomic_ptr_val_t* = atomic_ptr_t 12 | 13 | ## Low-level primitives come in several styles: 14 | 15 | ## Portable higher-level utilities: 16 | ## * 17 | ## @defgroup atomic_apis Atomic Services APIs 18 | ## @ingroup kernel_apis 19 | ## @{ 20 | ## 21 | ## * 22 | ## @brief Initialize an atomic variable. 23 | ## 24 | ## This macro can be used to initialize an atomic variable. For example, 25 | ## @code atomic_t my_var = ATOMIC_INIT(75); @endcode 26 | ## 27 | ## @param i Value to assign to atomic variable. 28 | ## 29 | 30 | proc ATOMIC_INIT*(i: cint): atomic_t {.importc: "ATOMIC_INIT", header: "atomic.h".} 31 | 32 | 33 | 34 | ## * 35 | ## @brief Initialize an atomic pointer variable. 36 | ## 37 | ## This macro can be used to initialize an atomic pointer variable. For 38 | ## example, 39 | ## @code atomic_ptr_t my_ptr = ATOMIC_PTR_INIT(&data); @endcode 40 | ## 41 | ## @param p Pointer value to assign to atomic pointer variable. 42 | ## 43 | proc ATOMIC_PTR_INIT*(p: pointer): atomic_ptr_t {.importc: "ATOMIC_PTR_INIT", header: "atomic.h".} 44 | 45 | 46 | # ## * 47 | # ## @brief Define an array of atomic variables. 48 | # ## 49 | # ## This macro defines an array of atomic variables containing at least 50 | # ## @a num_bits bits. 51 | # ## 52 | # ## @note 53 | # ## If used from file scope, the bits of the array are initialized to zero; 54 | # ## if used from within a function, the bits are left uninitialized. 55 | # ## 56 | # ## @cond INTERNAL_HIDDEN 57 | # ## @note 58 | # ## This macro should be replicated in the PREDEFINED field of the documentation 59 | # ## Doxyfile. 60 | # ## @endcond 61 | # ## 62 | # ## @param name Name of array of atomic variables. 63 | # ## @param num_bits Number of bits needed. 64 | # ## 65 | # proc ATOMIC_BITMAP_SIZE(num_bits: int): atomic_ptr_t {.importc: "ATOMIC_BITMAP_SIZE", header: "atomic.h".} 66 | # template ATOMIC_DEFINE*(name: untyped; num_bits: static[int]) = 67 | # var `name`: array[ATOMIC_BITMAP_SIZE(num_bits)] 68 | 69 | 70 | ## * 71 | ## @brief Atomically test a bit. 72 | ## 73 | ## This routine tests whether bit number @a bit of @a target is set or not. 74 | ## The target may be a single atomic variable or an array of them. 75 | ## 76 | ## @param target Address of atomic variable or array. 77 | ## @param bit Bit number (starting from 0). 78 | ## 79 | ## @return true if the bit was set, false if it wasn't. 80 | ## 81 | proc atomic_test_bit*(target: ptr atomic_t; bit: cint): bool {. 82 | importc: "$1", header: "atomic.h".} 83 | 84 | 85 | 86 | ## * 87 | ## @brief Atomically test and clear a bit. 88 | ## 89 | ## Atomically clear bit number @a bit of @a target and return its old value. 90 | ## The target may be a single atomic variable or an array of them. 91 | ## 92 | ## @param target Address of atomic variable or array. 93 | ## @param bit Bit number (starting from 0). 94 | ## 95 | ## @return true if the bit was set, false if it wasn't. 96 | ## 97 | proc atomic_test_and_clear_bit*(target: ptr atomic_t; bit: cint): bool {. 98 | importc: "$1", header: "atomic.h".} 99 | 100 | 101 | 102 | ## * 103 | ## @brief Atomically set a bit. 104 | ## 105 | ## Atomically set bit number @a bit of @a target and return its old value. 106 | ## The target may be a single atomic variable or an array of them. 107 | ## 108 | ## @param target Address of atomic variable or array. 109 | ## @param bit Bit number (starting from 0). 110 | ## 111 | ## @return true if the bit was set, false if it wasn't. 112 | ## 113 | proc atomic_test_and_set_bit*(target: ptr atomic_t; bit: cint): bool {. 114 | importc: "$1", header: "atomic.h".} 115 | 116 | 117 | 118 | ## * 119 | ## @brief Atomically clear a bit. 120 | ## 121 | ## Atomically clear bit number @a bit of @a target. 122 | ## The target may be a single atomic variable or an array of them. 123 | ## 124 | ## @param target Address of atomic variable or array. 125 | ## @param bit Bit number (starting from 0). 126 | ## 127 | ## @return N/A 128 | ## 129 | 130 | proc atomic_clear_bit*(target: ptr atomic_t; bit: cint) {. 131 | importc: "$1", header: "atomic.h".} 132 | 133 | 134 | 135 | ## * 136 | ## @brief Atomically set a bit. 137 | ## 138 | ## Atomically set bit number @a bit of @a target. 139 | ## The target may be a single atomic variable or an array of them. 140 | ## 141 | ## @param target Address of atomic variable or array. 142 | ## @param bit Bit number (starting from 0). 143 | ## 144 | ## @return N/A 145 | ## 146 | proc atomic_set_bit*(target: ptr atomic_t; bit: cint) {. 147 | importc: "$1", header: "atomic.h".} 148 | 149 | 150 | 151 | ## * 152 | ## @brief Atomically set a bit to a given value. 153 | ## 154 | ## Atomically set bit number @a bit of @a target to value @a val. 155 | ## The target may be a single atomic variable or an array of them. 156 | ## 157 | ## @param target Address of atomic variable or array. 158 | ## @param bit Bit number (starting from 0). 159 | ## @param val true for 1, false for 0. 160 | ## 161 | ## @return N/A 162 | ## 163 | proc atomic_set_bit_to*(target: ptr atomic_t; bit: cint; val: bool) {. 164 | importc: "$1", header: "atomic.h".} 165 | 166 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zcmtoken.nim: -------------------------------------------------------------------------------- 1 | import std/[macros, strutils] 2 | 3 | import cdecl/cdeclapi 4 | 5 | 6 | type 7 | cmtoken* = distinct string 8 | cminvtoken* = distinct pointer 9 | 10 | macro CDefineToken*(name: varargs[untyped]): cmtoken = 11 | let tokenStr = newLit(name.repr) 12 | result = quote do: 13 | cmtoken(`tokenStr`) 14 | 15 | macro CDeclartionInvoke*(defineName: untyped, name: varargs[untyped]) = 16 | ## Calls a C Defines Macro as a declaration 17 | ## Useful for C macros that define a struct or variable 18 | ## at the top level 19 | let macroInvokeName = newLit( defineName.repr & "(" & name.repr & ");") 20 | result = quote do: 21 | {.emit: `macroInvokeName`.} 22 | 23 | macro CDefineExpression*(name: untyped, macroInvocation: untyped, retType: typedesc) = 24 | ## Defines a "variable" which is really a macro expression 25 | ## e.g. CDefineExpression(DEVICE_NAME_ID, DEVICE_NAME_ID(Id)): int 26 | ## will define 27 | let macroInvokeName = newLit( macroInvocation.repr ) 28 | let rt = parseExpr(retType.repr) 29 | result = quote do: 30 | var `name` {.importc: `macroInvokeName`, global, noinit, nodecl.}: `rt` 31 | 32 | macro CTOKEN*(macroInvocation: untyped): cminvtoken = 33 | let macroInvokeName = newLit( macroInvocation.repr ) 34 | result = quote do: 35 | var mi {.importc: `macroInvokeName`, global, noinit, nodecl.}: cminvtoken 36 | mi 37 | 38 | macro CM_PROC*(macroName: untyped, margs: untyped): untyped = 39 | # echo "\nCM_PROC: " 40 | # echo "MCM_PROC:MN =", macroName.treeRepr 41 | # echo "MCM_PROC:ARGS =", margs.treeRepr 42 | # echo "MARGS expand =", margs.expandMacros.treeRepr 43 | let mn = macroname.repr 44 | 45 | var label: string 46 | echo "margs:kind: ", margs.kind 47 | if margs.kind == nnkIdent: 48 | # assert margs.strVal == "tok" 49 | label = margs.strVal 50 | elif margs.kind == nnkStrLit: 51 | echo "margs:str: ", margs.strVal 52 | label = margs.strVal 53 | elif margs.kind == nnkRStrLit: 54 | echo "margs:str: ", margs.strVal 55 | label = margs.strVal 56 | else: 57 | margs.expectKind(nnkCallStrLit) 58 | # margs[0].expectKind(nnkIdent) 59 | margs[1].expectKind(nnkRStrLit) 60 | assert margs[0].strVal == "tok" 61 | label = margs[1].strVal 62 | 63 | echo "label: ", label 64 | let 65 | # label = margs[1].strVal 66 | mas = mn & "(" & label & ")" 67 | ma = newLit mas 68 | result = quote do: 69 | var mi2 {.importc: `ma`, global, nodecl, noinit.}: cminvtoken 70 | mi2 71 | 72 | proc mkTokPsuedoVar(nm: string): NimNode {.compileTime.} = 73 | let mi = newLit(nm) 74 | result = quote do: 75 | var mi2 {.importc: `mi`, global, nodecl, noinit.}: cminvtoken 76 | mi2 77 | 78 | proc tokCompFmt(sfmt: string, args: varargs[string]): string {.compileTime.} = 79 | result = sfmt % args 80 | 81 | 82 | macro `tok`*(token: untyped): cminvtoken = 83 | let nm: string = 84 | if token.kind == nnkAccQuoted: 85 | token.expectKind({nnkAccQuoted, nnkRStrLit}) 86 | token.expectLen(1) 87 | token[0].strVal 88 | elif token.kind == nnkRStrLit: 89 | token.strVal 90 | elif token.kind == nnkStrLit: 91 | token.strVal 92 | else: 93 | echo "tok args: ", token.treeRepr 94 | error("tok must be used like 'tok\"MYCTOKEN\"' or 'tok`MYCTOKEN`' ", token) 95 | raise newException(ValueError, "tok error") 96 | result = mkTokPsuedoVar(nm) 97 | 98 | 99 | macro tokFrom*(nm: static[string]): cminvtoken = 100 | result = mkTokPsuedoVar(nm) 101 | 102 | 103 | macro ctokFromUntypedWithFmt*(strfmt: string, token: untyped): cminvtoken = 104 | let nm = strfmt.strVal % symbolName(token) 105 | let mi = newLit(nm) 106 | result = quote do: 107 | var mi2 {.importc: `mi`, global, nodecl, noinit.}: cminvtoken 108 | mi2 109 | 110 | template tokFromFmt*(sfmt: static[string], token: static[string]): cminvtoken = 111 | tokFrom(tokCompFmt(sfmt, token)) 112 | 113 | 114 | macro CDefineDeclareVar*(name: untyped, macroRepr: untyped, retType: typedesc) = 115 | let macroInvokeName = newLit( macroRepr.repr ) 116 | let rt = parseExpr(retType.repr) 117 | result = quote do: 118 | var myMacroVar {.importc: `macroInvokeName`, global, noinit, nodecl.}: `rt` 119 | var `name`* = myMacroVar 120 | 121 | macro toString*(token: cminvtoken): string = 122 | echo "token.repr: ", token.repr 123 | echo "token MARGS expand =", token.expandMacros.treeRepr 124 | result = newLit(token.treerepr) 125 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zconfs.nim: -------------------------------------------------------------------------------- 1 | 2 | import tables, streams, parsecfg, strutils 3 | import json 4 | import macros 5 | 6 | const 7 | ZephyrConfigFile* {.strdefine.} = "" 8 | 9 | ## Current constants 10 | ## 11 | ## add more constant defines as needed to match Zephyr 12 | const CONFIG_NAMES = [ 13 | "ADC_ASYNC", 14 | "ADC_CONFIGURABLE_INPUTS", 15 | "BOOT_FLEXSPI_NOR", 16 | "DMA_64BIT", 17 | "DEMAND_PAGING_THREAD_STATS", 18 | "ERRNO", 19 | "ERRNO_IN_TLS", 20 | "EVENTFD", 21 | "FLASH_PAGE_LAYOUT", 22 | "FPU_SHARING", 23 | "HAS_MCUX_FLEXSPI", 24 | "INIT_STACKS", 25 | "MPU", 26 | "MULTITHREADING", 27 | "MEM_SLAB_TRACE_MAX_UTILIZATION", 28 | # Net options 29 | "NETWORKING", 30 | # Net generic 31 | "NET_L2_PPP", 32 | "NET_L2_VIRTUAL", 33 | "NET_OFFLOAD", 34 | "NET_SOCKETS_OFFLOAD", 35 | "NET_STATISTICS_PER_INTERFACE", 36 | "NET_POWER_MANAGEMENT", 37 | "NET_PKT_TIMESTAMP", 38 | "NET_NATIVE", 39 | "NET_L2_IEEE802154", 40 | # IPv4 stuffs 41 | "NET_DHCPV4", 42 | "NET_IPV4", 43 | "NET_IPV4_AUTO", 44 | "NET_NATIVE_IPV4", 45 | "NET_IF_UNICAST_IPV4_ADDR_COUNT", 46 | "NET_IF_MCAST_IPV4_ADDR_COUNT", 47 | # IPv6 stuffs 48 | "NET_IPV6", 49 | "NET_NATIVE_IPV6", 50 | "NET_IF_UNICAST_IPV6_ADDR_COUNT", 51 | "NET_IF_MCAST_IPV6_ADDR_COUNT", 52 | "NET_IPV6_DAD", 53 | "NET_IPV6_ND", 54 | "NET_IPV6_NBR_CACHE", 55 | "NET_IPV6_FRAGMENT", 56 | "NET_IF_IPV6_PREFIX_COUNT", 57 | "NVS", 58 | # Net done 59 | "PM", 60 | "PM_DEVICE", 61 | "POLL", 62 | "PRINTK", 63 | "SCHED_CPU_MASK", 64 | "SCHED_DEADLINE", 65 | "SCHED_DUMB", 66 | "SMP", 67 | "SPI_ASYNC", 68 | "SYS_CLOCK_EXISTS", 69 | "THREAD_CUSTOM_DATA", 70 | "THREAD_LOCAL_STORAGE", 71 | "THREAD_MONITOR", 72 | "THREAD_NAME", 73 | "THREAD_RUNTIME_STATS", 74 | "THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS", 75 | "THREAD_STACK_INFO", 76 | "THREAD_USERSPACE_LOCAL_DATA", 77 | "TICKLESS_KERNEL", 78 | "TIMEOUT_64BIT", 79 | "TIMER_HAS_64BIT_CYCLE_COUNTER", 80 | "TIMESLICING", 81 | "USB_DEVICE_STACK", 82 | "USERSPACE", 83 | "USE_SWITCH", 84 | "WAITQ_SCALABLE", 85 | "X86", 86 | "X86_SSE", 87 | ] 88 | 89 | template other_configs(): seq[(string, NimNode)] = 90 | @[ 91 | ("ARCH_EXCEPT", newLit(true)), 92 | # ("BOARD", newLit("native_posix")), 93 | ] 94 | 95 | proc parseCmakeConfig*(configName=".config"): TableRef[string, JsonNode] = 96 | var 97 | fpath = configName 98 | echo "Using CMAKE Config file: ", fpath 99 | var 100 | f = readFile(fpath) 101 | fs = newStringStream(f) 102 | opts = newTable[string, JsonNode]() 103 | 104 | if fs != nil: 105 | var p: CfgParser 106 | open(p, fs, "zephyr.config") 107 | while true: 108 | var e = next(p) 109 | case e.kind 110 | of cfgEof: break 111 | of cfgSectionStart: ## a ``[section]`` has been parsed 112 | echo("warning ignoring new config section: " & e.section) 113 | of cfgKeyValuePair: 114 | # echo("key-value-pair: " & e.key & ": " & e.value) 115 | if e.value == "y": 116 | opts[e.key] = % true 117 | elif e.value != "n": 118 | var jn = 119 | try: 120 | % fromHex[int](e.value) 121 | except ValueError: 122 | try: 123 | % parseInt(e.value) 124 | except ValueError: 125 | echo "unknown: config flag: ", e.key ," value: ", repr e.value 126 | % e.value 127 | 128 | opts[e.key] = jn 129 | of cfgOption: 130 | echo("warning ignoring config option: " & e.key & ": " & e.value) 131 | of cfgError: 132 | echo(e.msg) 133 | close(p) 134 | 135 | result = opts 136 | 137 | macro GenerateZephyrConfigDefines*(): untyped = 138 | let cvals: TableRef[string, JsonNode] = 139 | if ZephyrConfigFile == "": 140 | var tbl = newTable[string,JsonNode]() 141 | for name in CONFIG_NAMES: 142 | tbl[name] = % true 143 | tbl 144 | else: 145 | parseCmakeConfig(ZephyrConfigFile) 146 | 147 | proc getCVal(name: string, defval: NimNode = nil): NimNode = 148 | let jnode = cvals.getOrDefault("CONFIG_" & name, newJNull()) 149 | # echo "jnode: ", repr jnode 150 | if jnode.kind == JBool: 151 | result = newLit(jnode.getBool()) 152 | elif jnode.kind == JInt: 153 | result = newLit(jnode.getInt()) 154 | elif jnode.kind == JFloat: 155 | result = newLit(jnode.getFloat()) 156 | elif jnode.kind == JString: 157 | result = newLit(jnode.getStr()) 158 | elif jnode.kind == JNull: 159 | if defval.isNil: 160 | result = newLit(false) 161 | else: 162 | result = defval 163 | else: 164 | error("unhandled config flag: " & name & " type: " & $jnode) 165 | 166 | result = newStmtList() 167 | for name in CONFIG_NAMES: 168 | let confFlag = ident "CONFIG_" & name 169 | let cval = name.getCVal() 170 | result.add quote do: 171 | const `confFlag`* = `cval` 172 | 173 | for (name, defval) in other_configs(): 174 | assert typeof(name) is string 175 | assert typeof(defval) is NimNode 176 | let confFlag = ident name 177 | var cval = name.getCVal(defval) 178 | result.add quote do: 179 | const `confFlag`* = `cval` 180 | 181 | # TODO: FIXME: finish implementing! 182 | GenerateZephyrConfigDefines() 183 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zdevicetree.nim: -------------------------------------------------------------------------------- 1 | import zcmtoken 2 | import zdevice 3 | 4 | export zcmtoken 5 | export zdevice 6 | 7 | template DT_NODELABEL*(ma: untyped): cminvtoken = 8 | CM_PROC(DT_NODELABEL, ma) 9 | 10 | template DT_ALIAS*(ma: untyped): cminvtoken = 11 | CM_PROC(DT_ALIAS, ma) 12 | 13 | proc DT_LABEL*(name: cminvtoken): cstring {.importc: "$1", header: "devicetree.h".} 14 | 15 | template dt*(ma: static string): cminvtoken = 16 | tok`ma` 17 | 18 | template alias*(ma: untyped): cminvtoken = 19 | DT_ALIAS(ma) 20 | 21 | type 22 | nDevice* = object 23 | name: string 24 | 25 | template nDeviceTree*(nd: static[string]): static[nDevice] = 26 | nDevice(name: nd) 27 | 28 | proc DT_CHOSEN*(name: cminvtoken): ptr device {.importc: "$1", header: "devicetree.h".} ##\ 29 | ## 30 | ## @brief Get a node identifier for a /chosen node property 31 | ## 32 | ## This is only valid to call if DT_HAS_CHOSEN(prop) is 1. 33 | ## @param prop lowercase-and-underscores property name for 34 | ## the /chosen node 35 | ## @return a node identifier for the chosen node property 36 | ## 37 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zkernel_fixes.nim: -------------------------------------------------------------------------------- 1 | 2 | import wrapper_utils 3 | 4 | export wrapper_utils 5 | 6 | proc abort*() {.importc: "abort", header: "stdlib.h".} 7 | 8 | proc k_sys_reboot*(kind: cint) {.importc: "sys_reboot", header: "".} 9 | 10 | proc printk*(frmt: cstring) {.importc: "$1", varargs, header: "".} 11 | 12 | macro zsyscall*(fn: untyped) = result = fn 13 | 14 | # __syscall k_tid_t k_thread_create(struct k_thread *new_thread, 15 | # k_thread_stack_t *stack, 16 | # size_t stack_size, 17 | # k_thread_entry_t entry, 18 | # void *p1, void *p2, void *p3, 19 | # int prio, uint32_t options, k_timeout_t delay); 20 | type 21 | 22 | k_thread_stack_t* {.importc: "$1", header: "", bycopy, incompleteStruct.} = object 23 | 24 | k_thread_entry_t* {.importc: "$1 ", header: "".} = proc (p1, p2, p3: pointer) {.cdecl.} 25 | 26 | k_thread_proc* = proc (p1, p2, p3: pointer) {.cdecl.} 27 | 28 | z_wait_q_t* {.importc: "_wait_q_t", header: "", bycopy, incompleteStruct.} = object 29 | waitq {.importc: "$1".}: sys_dlist_t 30 | 31 | # these are all opaque kernel types 32 | # sys_snode_t* {.importc: "sys_snode_t", header: "slist.h", bycopy.} = object ##\ 33 | sys_snode_t* {.importc: "$1", header: "", 34 | bycopy, incompleteStruct.} = object 35 | next {.importc: "$1".}: ptr sys_snode_t 36 | sys_slist_t* {.importc: "$1", header: "", 37 | bycopy, incompleteStruct.} = object 38 | head: pointer 39 | tail: pointer 40 | 41 | sys_sfnode_t* {.importc: "$1", header: "", 42 | bycopy, incompleteStruct.} = object 43 | next_and_flags {.importc: "$1".}: cuint 44 | sys_sflist_t* {.importc: "$1", header: "", 45 | bycopy, incompleteStruct.} = object 46 | head: pointer 47 | tail: pointer 48 | 49 | dnode* {.importc: "struct _dnode", header: "", 50 | bycopy, incompleteStruct.} = object 51 | head {.importc: "$1".}: pointer 52 | next {.importc: "$1".}: pointer 53 | sys_dlist_t* {.importc: "$1", header: "", 54 | bycopy, incompleteStruct.} = dnode 55 | sys_dnode_t* {.importc: "$1", header: "", 56 | bycopy, incompleteStruct.} = dnode 57 | 58 | k_spinlock* {.importc: "struct $1", header: "", bycopy, incompleteStruct.} = object 59 | 60 | k_priv_timeout* {.importc: "struct _timeout", header: "", bycopy, incompleteStruct.} = object 61 | 62 | k_mem_block* {.importc: "struct k_mem_block", header: "", bycopy, incompleteStruct.} = object 63 | 64 | off_t* = csize ##\ 65 | ## Offset type size. it's a ssizt_t, aka a signed csize_t in C. For historical reasons this is csize in nim 66 | 67 | # proc K_MSEC*(ts: int): k_timeout_t {.importc: "$1", header: "".} 68 | 69 | when defined(NephyrDebugSfList): 70 | proc sys_sflist_peek_head(list: ptr sys_sflist_t): ptr sys_sfnode_t {.importc: "$1", header: "".} 71 | proc sys_sflist_peek_next(list: ptr sys_sfnode_t): ptr sys_sfnode_t {.importc: "$1", header: "".} 72 | 73 | proc repr*(val: sys_sflist_t): string = 74 | 75 | var 76 | node: ptr sys_sfnode_t = sys_sflist_peek_head(addr val) 77 | dlist = newSeq[pointer]() 78 | 79 | while node != nil: 80 | echo "slist: node: ", repr(node.pointer) 81 | dlist.add(node.pointer) 82 | node = sys_sflist_peek_next(node) 83 | 84 | return "slist: " & repr(dlist) 85 | 86 | when defined(NephyrDebugSList): 87 | proc sys_slist_peek_head(list: ptr sys_slist_t): ptr sys_snode_t {.importc: "$1", header: "".} 88 | proc sys_slist_peek_next(list: ptr sys_slist_t, node: ptr sys_snode_t): ptr sys_snode_t {.importc: "$1", header: "".} 89 | 90 | proc repr*(val: sys_slist_t): string = 91 | 92 | var 93 | node: ptr sys_snode_t = sys_slist_peek_head(addr val) 94 | dlist = newSeq[pointer]() 95 | 96 | while node != nil: 97 | echo "slist: node: ", repr(node.pointer) 98 | dlist.add(node.pointer) 99 | node = sys_slist_peek_next(addr val, node) 100 | 101 | return "slist: " & repr(dlist) 102 | 103 | when defined(NephyrDebugDList): 104 | proc sys_dlist_peek_head(list: ptr sys_dlist_t): ptr sys_dnode_t {.importc: "$1", header: "".} 105 | proc sys_dlist_peek_next(list, node: ptr sys_dlist_t): ptr sys_dnode_t {.importc: "$1", header: "".} 106 | 107 | proc repr*(val: sys_dlist_t): string = 108 | 109 | var 110 | node: ptr dnode = sys_dlist_peek_head(addr val) 111 | dlist = newSeq[pointer]() 112 | 113 | while node != nil: 114 | echo "dlist: node: ", repr(node.pointer) 115 | dlist.add(node.pointer) 116 | node = sys_dlist_peek_next(addr val, node) 117 | 118 | return "dlist: " & repr(dlist) 119 | 120 | proc K_THREAD_STACK_SIZEOF*(stack: ptr k_thread_stack_t): csize_t {. 121 | importc: "$1", header: "".} 122 | # proc K_THREAD_STACK_DEFINE*(stack_area: cminvtoken, size: csize_t) {. 123 | # importc: "$1", header: "".} 124 | 125 | # # K thread create 126 | # proc k_thread_create*(new_thread: ptr k_thread, 127 | # stack: ptr k_thread_stack_t, 128 | # stack_size: csize_t, 129 | # entry: k_thread_proc, 130 | # p1, p2, p3: pointer, 131 | # prio: cint, 132 | # options: uint32, 133 | # delay: k_timeout_t): k_tid_t {. 134 | # importc: "k_thread_create", header: "".} 135 | 136 | import macros 137 | macro getSymbolName*(x: typed): string = x.toStrLit 138 | 139 | template KDefineStack*(name: untyped, size: static[int]) = 140 | var name* {.inject, importc, nodecl.}: ptr k_thread_stack_t 141 | {.emit: "/*TYPESECTION*/ K_KERNEL_STACK_DEFINE($1, $2);" % [ getSymbolName(name), $size, ] .} 142 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zmcuboot.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2017 Nordic Semiconductor ASA 3 | ## Copyright (c) 2016 Linaro Limited 4 | ## 5 | ## SPDX-License-Identifier: Apache-2.0 6 | ## 7 | 8 | const hdrmcu = "" 9 | 10 | var 11 | BOOT_SWAP_TYPE_NONE* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 12 | # * Attempt to boot the contents of slot 0. 13 | BOOT_SWAP_TYPE_TEST* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 14 | # * Swap to slot 1. Absent a confirm command, revert back on next boot. 15 | BOOT_SWAP_TYPE_PERM* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 16 | # * Swap to slot 1, and permanently switch to booting its contents. 17 | BOOT_SWAP_TYPE_REVERT* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 18 | # * Swap back to alternate slot. A confirm changes this state to NONE. 19 | BOOT_SWAP_TYPE_FAIL* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 20 | # * Swap failed because image to be run is not valid 21 | BOOT_IMG_VER_STRLEN_MAX* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 22 | # * max strlen 23 | 24 | type 25 | BtSwapType* {.size: sizeof(cint).} = enum 26 | swNone = 1, 27 | swTest = 2, 28 | swPerm = 3, 29 | swRevert = 4, 30 | swFail = 5 31 | 32 | ## Trailer: 33 | var 34 | BOOT_MAX_ALIGN* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 35 | BOOT_MAGIC_SZ* {.importc: "$1", header: hdrmcu, nodecl.}: cint #\ 36 | 37 | proc BOOT_TRAILER_IMG_STATUS_OFFS*(bank_area: csize_t): csize_t {.importc: "$1", header: hdrmcu.} 38 | 39 | ## * 40 | ## @brief MCUboot image header representation for image version 41 | ## 42 | ## The header for an MCUboot firmware image contains an embedded 43 | ## version number, in semantic versioning format. This structure 44 | ## represents the information it contains. 45 | ## 46 | 47 | type 48 | mcuboot_img_sem_ver* {.bycopy.} = object 49 | major*: uint8 50 | minor*: uint8 51 | revision*: uint16 52 | build_num*: uint32 53 | 54 | 55 | ## * 56 | ## @brief Model for the MCUboot image header as of version 1 57 | ## 58 | ## This represents the data present in the image header, in version 1 59 | ## of the header format. 60 | ## 61 | ## Some information present in the header but not currently relevant 62 | ## to applications is omitted. 63 | ## 64 | 65 | type 66 | mcuboot_img_header_v1* {.bycopy.} = object 67 | image_size*: uint32 ## * The size of the image, in bytes. 68 | sem_ver*: mcuboot_img_sem_ver ## * The image version. 69 | 70 | 71 | ## * 72 | ## @brief Model for the MCUBoot image header 73 | ## 74 | ## This contains the decoded image header, along with the major 75 | ## version of MCUboot that the header was built for. 76 | ## 77 | ## (The MCUboot project guarantees that incompatible changes to the 78 | ## image header will result in major version changes to the bootloader 79 | ## itself, and will be detectable in the persistent representation of 80 | ## the header.) 81 | ## 82 | 83 | type 84 | mcuboot_version_union* {.bycopy, union.} = object 85 | v1*: mcuboot_img_header_v1 ## * Header information for MCUboot version 1. 86 | 87 | mcuboot_img_header* {.bycopy.} = object 88 | mcuboot_version*: uint32 ## * 89 | ## The version of MCUboot the header is built for. 90 | ## 91 | ## The value 1 corresponds to MCUboot versions 1.x.y. 92 | ## 93 | ## * 94 | ## The header information. It is only valid to access fields 95 | ## in the union member corresponding to the mcuboot_version 96 | ## field above. 97 | ## 98 | h*: mcuboot_version_union 99 | 100 | 101 | ## * 102 | ## @brief Read the MCUboot image header information from an image bank. 103 | ## 104 | ## This attempts to parse the image header, 105 | ## From the start of the @a area_id image. 106 | ## 107 | ## @param area_id flash_area ID of image bank which stores the image. 108 | ## @param header On success, the returned header information is available 109 | ## in this structure. 110 | ## @param header_size Size of the header structure passed by the caller. 111 | ## If this is not large enough to contain all of the 112 | ## necessary information, an error is returned. 113 | ## @return Zero on success, a negative value on error. 114 | ## 115 | proc boot_read_bank_header*(area_id: uint8; header: ptr mcuboot_img_header; 116 | header_size: csize_t): cint {. 117 | importc: "boot_read_bank_header", header: hdrmcu.} 118 | 119 | 120 | ## * 121 | ## @brief Check if the currently running image is confirmed as OK. 122 | ## 123 | ## MCUboot can perform "test" upgrades. When these occur, a new 124 | ## firmware image is installed and booted, but the old version will be 125 | ## reverted at the next reset unless the new image explicitly marks 126 | ## itself OK. 127 | ## 128 | ## This routine can be used to check if the currently running image 129 | ## has been marked as OK. 130 | ## 131 | ## @return True if the image is confirmed as OK, false otherwise. 132 | ## @see boot_write_img_confirmed() 133 | ## 134 | proc boot_is_img_confirmed*(): bool {.importc: "boot_is_img_confirmed", header: hdrmcu.} 135 | 136 | 137 | ## * 138 | ## @brief Marks the currently running image as confirmed. 139 | ## 140 | ## This routine attempts to mark the currently running firmware image 141 | ## as OK, which will install it permanently, preventing MCUboot from 142 | ## reverting it for an older image at the next reset. 143 | ## 144 | ## This routine is safe to call if the current image has already been 145 | ## confirmed. It will return a successful result in this case. 146 | ## 147 | ## @return 0 on success, negative errno code on fail. 148 | ## 149 | proc boot_write_img_confirmed*(): cint {.importc: "boot_write_img_confirmed", header: hdrmcu.} 150 | 151 | 152 | ## * 153 | ## @brief Determines the action, if any, that mcuboot will take on the next 154 | ## reboot. 155 | ## @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on 156 | ## fail. 157 | ## 158 | proc mcuboot_swap_type*(): cint {.importc: "mcuboot_swap_type", header: hdrmcu.} 159 | 160 | ## * Boot upgrade request modes 161 | const 162 | BOOT_UPGRADE_TEST* = 0 163 | BOOT_UPGRADE_PERMANENT* = 1 164 | 165 | ## * 166 | ## @brief Marks the image in slot 1 as pending. On the next reboot, the system 167 | ## will perform a boot of the slot 1 image. 168 | ## 169 | ## @param permanent Whether the image should be used permanently or 170 | ## only tested once: 171 | ## BOOT_UPGRADE_TEST=run image once, then confirm or revert. 172 | ## BOOT_UPGRADE_PERMANENT=run image forever. 173 | ## @return 0 on success, negative errno code on fail. 174 | ## 175 | proc boot_request_upgrade*(permanent: cint): cint {.importc: "boot_request_upgrade", header: hdrmcu.} 176 | 177 | 178 | ## * 179 | ## @brief Erase the image Bank. 180 | ## 181 | ## @param area_id flash_area ID of image bank to be erased. 182 | ## @return 0 on success, negative errno code on fail. 183 | ## 184 | proc boot_erase_img_bank*(area_id: uint8): cint {.importc: "boot_erase_img_bank", header: hdrmcu.} 185 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zsys_clock.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2014-2015 Wind River Systems, Inc. 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | ## * 7 | ## @file 8 | ## @brief Variables needed for system clock 9 | ## 10 | ## 11 | ## Declare variables used by both system timer device driver and kernel 12 | ## components that use timer functionality. 13 | ## 14 | 15 | ## * 16 | ## @addtogroup clock_apis 17 | ## @{ 18 | ## 19 | ## * 20 | ## @brief Tick precision used in timeout APIs 21 | ## 22 | ## This type defines the word size of the timeout values used in 23 | ## k_timeout_t objects, and thus defines an upper bound on maximum 24 | ## timeout length (or equivalently minimum tick duration). Note that 25 | ## this does not affect the size of the system uptime counter, which 26 | ## is always a 64 bit count of ticks. 27 | ## 28 | 29 | import zconfs 30 | 31 | when CONFIG_TIMEOUT_64BIT: 32 | type 33 | k_ticks_t* = int64 34 | else: 35 | type 36 | k_ticks_t* = uint32 37 | 38 | var K_TICKS_FOREVER* {.importc: "K_TICKS_FOREVER", header: "sys_clock.h".}: int 39 | 40 | 41 | type 42 | k_timeout_t* {.importc: "k_timeout_t", header: "sys_clock.h", incompleteStruct, bycopy.} = object 43 | ## * 44 | ## @brief Kernel timeout type 45 | ## 46 | ## Timeout arguments presented to kernel APIs are stored in this 47 | ## opaque type, which is capable of representing times in various 48 | ## formats and units. It should be constructed from application data 49 | ## using one of the macros defined for this purpose (e.g. `K_MSEC()`, 50 | ## `K_TIMEOUT_ABS_TICKS()`, etc...), or be one of the two constants 51 | ## K_NO_WAIT or K_FOREVER. Applications should not inspect the 52 | ## internal data once constructed. Timeout values may be compared for 53 | ## equality with the `K_TIMEOUT_EQ()` macro. 54 | ## 55 | 56 | ticks* {.importc: "ticks".}: k_ticks_t 57 | 58 | 59 | proc K_TIMEOUT_EQ*(a: k_timeout_t; b: k_timeout_t) {.importc: "K_TIMEOUT_EQ", 60 | header: "sys_clock.h".} ## * 61 | ## @brief Compare timeouts for equality 62 | ## 63 | ## The k_timeout_t object is an opaque struct that should not be 64 | ## inspected by application code. This macro exists so that users can 65 | ## test timeout objects for equality with known constants 66 | ## (e.g. K_NO_WAIT and K_FOREVER) when implementing their own APIs in 67 | ## terms of Zephyr timeout constants. 68 | ## 69 | ## @return True if the timeout objects are identical 70 | ## 71 | 72 | 73 | var Z_TIMEOUT_NO_WAIT* {.importc: "Z_TIMEOUT_NO_WAIT", header: "sys_clock.h".}: int 74 | 75 | var Z_FOREVER* {.importc: "Z_FOREVER", header: "sys_clock.h".}: int 76 | 77 | proc Z_TIMEOUT_MS*(t: k_ticks_t): k_timeout_t {.importc: "Z_TIMEOUT_MS", header: "sys_clock.h".} 78 | proc Z_TIMEOUT_US*(t: k_ticks_t): k_timeout_t {.importc: "Z_TIMEOUT_US", header: "sys_clock.h".} 79 | proc Z_TIMEOUT_NS*(t: k_ticks_t): k_timeout_t {.importc: "Z_TIMEOUT_NS", header: "sys_clock.h".} 80 | proc Z_TIMEOUT_CYC*(t: k_ticks_t): k_timeout_t {.importc: "Z_TIMEOUT_CYC", header: "sys_clock.h".} 81 | 82 | proc Z_TICK_ABS*(t: k_ticks_t): k_ticks_t {.importc: "Z_TICK_ABS", header: "sys_clock.h".} ## Converts between absolute timeout expiration values (packed into 83 | ## the negative space below K_TICKS_FOREVER) and (non-negative) delta 84 | ## timeout values. If the result of Z_TICK_ABS(t) is >= 0, then the 85 | ## value was an absolute timeout with the returend expiration time. 86 | ## Note that this macro is bidirectional: Z_TICK_ABS(Z_TICK_ABS(t)) == 87 | ## t for all inputs, and that the representation of K_TICKS_FOREVER is 88 | ## the same value in both spaces! Clever, huh? 89 | ## 90 | 91 | 92 | when CONFIG_TICKLESS_KERNEL: 93 | proc z_enable_sys_clock*() {.importc: "z_enable_sys_clock", header: "sys_clock.h".} 94 | 95 | var NSEC_PER_USEC* {.importc: "NSEC_PER_USEC", header: "sys_clock.h".}: int ## number of nsec per usec 96 | 97 | var USEC_PER_MSEC* {.importc: "USEC_PER_MSEC", header: "sys_clock.h".}: int ## number of microseconds per millisecond 98 | 99 | var MSEC_PER_SEC* {.importc: "MSEC_PER_SEC", header: "sys_clock.h".}: int ## number of milliseconds per second 100 | 101 | var USEC_PER_SEC* {.importc: "USEC_PER_SEC", header: "sys_clock.h".}: int ## number of microseconds per second 102 | 103 | var NSEC_PER_SEC* {.importc: "NSEC_PER_SEC", header: "sys_clock.h".}: int ## number of nanoseconds per second 104 | 105 | ## kernel clocks 106 | ## 107 | ## We default to using 64-bit intermediates in timescale conversions, 108 | ## but if the HW timer cycles/sec, ticks/sec and ms/sec are all known 109 | ## to be nicely related, then we can cheat with 32 bits instead. 110 | ## 111 | 112 | proc SYS_CLOCK_HW_CYCLES_TO_NS_AVG*(X: uint32; NCYCLES: uint32) {. 113 | importc: "SYS_CLOCK_HW_CYCLES_TO_NS_AVG", header: "sys_clock.h".} ## 114 | ## SYS_CLOCK_HW_CYCLES_TO_NS_AVG converts CPU clock cycles to nanoseconds 115 | ## and calculates the average cycle time 116 | ## 117 | 118 | proc sys_clock_tick_get_32*(): uint32 {.importc: "sys_clock_tick_get_32", 119 | header: "sys_clock.h".} ## * 120 | ## 121 | ## @brief Return the lower part of the current system tick count 122 | ## 123 | ## @return the current system tick count 124 | ## 125 | ## 126 | 127 | proc sys_clock_tick_get*(): int64 {.importc: "sys_clock_tick_get", 128 | header: "sys_clock.h".} ## * 129 | ## 130 | ## @brief Return the current system tick count 131 | ## 132 | ## @return the current system tick count 133 | ## 134 | ## 135 | 136 | proc sys_clock_tick_get*() {.importc: "sys_clock_tick_get", header: "sys_clock.h".} 137 | proc sys_clock_tick_get_32*() {.importc: "sys_clock_tick_get_32", 138 | header: "sys_clock.h".} 139 | 140 | proc sys_clock_timeout_end_calc*(timeout: k_timeout_t): uint64 {. 141 | importc: "sys_clock_timeout_end_calc", header: "sys_clock.h".} 142 | 143 | -------------------------------------------------------------------------------- /src/nephyr/zephyr/zthread.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2016, Wind River Systems, Inc. 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | 7 | ## ============================================ ## 8 | ## Wrapper for Zephyr thread.h 9 | ## Note: Mostly we just need to let Nim know that these types exist, not how they work. 10 | ## ============================================ ## 11 | 12 | ## * 13 | ## @typedef k_thread_entry_t 14 | ## @brief Thread entry point function type. 15 | ## 16 | ## A thread's entry point function is invoked when the thread starts executing. 17 | ## Up to 3 argument values can be passed to the function. 18 | ## 19 | ## The thread terminates execution permanently if the entry point function 20 | ## returns. The thread is responsible for releasing any shared resources 21 | ## it may own (such as mutexes and dynamically allocated memory), prior to 22 | ## returning. 23 | ## 24 | ## @param p1 First argument. 25 | ## @param p2 Second argument. 26 | ## @param p3 Third argument. 27 | ## 28 | ## @return N/A 29 | ## 30 | import zconfs 31 | import zkernel_fixes 32 | 33 | const hdr = "" 34 | 35 | when CONFIG_THREAD_MONITOR: 36 | type 37 | z_thread_entry* {.importc: "__thread_entry", header: hdr, incompleteStruct, bycopy.} = object 38 | pEntry* {.importc: "pEntry".}: k_thread_entry_t 39 | parameter1* {.importc: "parameter1".}: pointer 40 | parameter2* {.importc: "parameter2".}: pointer 41 | parameter3* {.importc: "parameter3".}: pointer 42 | 43 | ## can be used for creating 'dummy' threads, e.g. for pending on objects 44 | 45 | type 46 | q_thread* {.importc: "no_name", header: hdr, incompleteStruct, bycopy, union.} = object 47 | 48 | 49 | z_thread_base* {.importc: "_thread_base", header: hdr, incompleteStruct, bycopy.} = object 50 | 51 | # # qnode_dlist* {.importc: "qnode_dlist".}: sys_dnode_t # note part of anonymous C union 52 | # # qnode_rb* {.importc: "qnode_rb".}: rbnode # note part of anonymous C union 53 | 54 | # # C Union 55 | # # C union elem 1 56 | # sched_locked* {.importc: "sched_locked", header: hdr.}: uint8 # part of anonymous union / struct 57 | # prio* {.importc: "prio", header: hdr.}: int8 # part of anonymous union / struct 58 | # # C union elem 2 59 | # preempt* {.importc: "preempt".}: uint16 60 | # # end C union 61 | 62 | # pended_on* {.importc: "pended_on".}: ptr _wait_q_t 63 | 64 | user_options* {.importc: "user_options".}: uint8 ## user facing 'thread options'; values defined in include/kernel.h 65 | ## thread state 66 | thread_state* {.importc: "thread_state".}: uint8 67 | 68 | when CONFIG_SCHED_DEADLINE: 69 | prio_deadline* {.importc: "prio_deadline".}: cint 70 | 71 | order_key* {.importc: "order_key".}: uint32 72 | 73 | when CONFIG_SMP: 74 | is_idle* {.importc: "is_idle".}: uint8 ## True for the per-CPU idle threads 75 | cpu* {.importc: "cpu".}: uint8 ## CPU index on which thread was last run 76 | global_lock_count* {.importc: "global_lock_count".}: uint8 ## Recursive count of irq_lock() calls 77 | 78 | when CONFIG_SCHED_CPU_MASK: 79 | cpu_mask* {.importc: "cpu_mask".}: uint8 ## "May run on" bits for each CPU 80 | 81 | swap_data* {.importc: "swap_data".}: pointer ## data returned by APIs 82 | 83 | when CONFIG_SYS_CLOCK_EXISTS: 84 | timeout* {.importc: "timeout".}: k_priv_timeout # ## this thread's entry in a timeout queue 85 | 86 | 87 | # when CONFIG_THREAD_USERSPACE_LOCAL_DATA: 88 | # type 89 | # _thread_userspace_local_data* {.importc: "_thread_userspace_local_data", 90 | # header: hdr, bycopy.} = object 91 | # when CONFIG_ERRNO and not CONFIG_ERRNO_IN_TLS: 92 | # var errno_var* {.importc: "errno_var", header: hdr.}: cint 93 | 94 | # when CONFIG_THREAD_RUNTIME_STATS: 95 | # type 96 | # k_thread_runtime_stats* {.importc: "k_thread_runtime_stats", 97 | # header: hdr, bycopy.} = object 98 | # execution_cycles* {.importc: "execution_cycles", header: hdr.}: uint64 99 | 100 | 101 | # type 102 | # _thread_runtime_stats* {.importc: "_thread_runtime_stats", header: hdr, 103 | # bycopy.} = object 104 | # when CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS: ## Timestamp when last switched in 105 | # var last_switched_in* {.importc: "last_switched_in", header: hdr.}: timing_t 106 | # else: 107 | # var last_switched_in* {.importc: "last_switched_in", header: hdr.}: uint32 108 | # stats* {.importc: "stats".}: k_thread_runtime_stats_t 109 | 110 | type 111 | k_thread_runtime_stats_t* {.importc: "k_thread_runtime_stats_t", header: hdr, bycopy.} = object 112 | 113 | z_poller* {.importc: "z_poller", header: hdr, incompleteStruct, bycopy.} = object 114 | is_polling* {.importc: "is_polling".}: bool 115 | mode* {.importc: "mode".}: uint8 116 | 117 | 118 | ## * 119 | ## @ingroup thread_apis 120 | ## Thread Structure 121 | ## 122 | 123 | type 124 | k_thread* {.importc: "struct k_thread", header: hdr, incompleteStruct, bycopy.} = object 125 | base* {.importc: "base".}: z_thread_base ## * defined by the architecture, but all archs need these 126 | 127 | # callee_saved* {.importc: "callee_saved".}: _callee_saved ## * static thread init data 128 | # init_data* {.importc: "init_data".}: pointer ## * threads waiting in k_thread_join() 129 | # join_queue* {.importc: "join_queue".}: _wait_q_t 130 | 131 | # poller* {.importc: "poller", header: hdr.}: z_poller 132 | 133 | # when CONFIG_THREAD_MONITOR: 134 | # ## * thread entry and parameters description 135 | # entry* {.importc: "entry", header: hdr.}: __thread_entry 136 | # ## * next item in list of all threads 137 | # next_thread* {.importc: "next_thread", header: hdr.}: ptr k_thread 138 | 139 | # when CONFIG_THREAD_NAME: 140 | # ## * Thread name 141 | # name* {.importc: "name", header: hdr.}: array[CONFIG_THREAD_MAX_NAME_LEN, char] 142 | 143 | when CONFIG_THREAD_CUSTOM_DATA: 144 | ## * crude thread-local storage 145 | custom_data* {.importc: "custom_data".}: pointer 146 | 147 | when CONFIG_THREAD_USERSPACE_LOCAL_DATA: 148 | userspace_local_data* {.importc: "userspace_local_data".}: pointer 149 | 150 | when CONFIG_ERRNO and not CONFIG_ERRNO_IN_TLS: 151 | when not CONFIG_USERSPACE: 152 | ## * per-thread errno variable 153 | errno_var* {.importc: "errno_var".}: cint 154 | 155 | # when CONFIG_THREAD_STACK_INFO: 156 | # ## * Stack Info 157 | # stack_info* {.importc: "stack_info", header: hdr.}: _thread_stack_info 158 | 159 | # when CONFIG_USERSPACE: 160 | # ## * memory domain info of the thread 161 | # mem_domain_info* {.importc: "mem_domain_info", header: hdr.}: _mem_domain_info 162 | # ## * Base address of thread stack 163 | # stack_obj* {.importc: "stack_obj", header: hdr.}: ptr k_thread_stack_t 164 | # ## * current syscall frame pointer 165 | # syscall_frame* {.importc: "syscall_frame", header: hdr.}: pointer 166 | 167 | # when CONFIG_USE_SWITCH: 168 | # ## When using __switch() a few previously arch-specific items 169 | # ## become part of the core OS 170 | # ## 171 | # ## * z_swap() return value 172 | # swap_retval* {.importc: "swap_retval", header: hdr.}: cint 173 | # ## * Context handle returned via arch_switch() 174 | # switch_handle* {.importc: "switch_handle", header: hdr.}: pointer 175 | 176 | resource_pool* {.importc: "resource_pool".}: pointer ## * resource pool 177 | 178 | when CONFIG_THREAD_LOCAL_STORAGE: 179 | ## Pointer to arch-specific TLS area 180 | tls* {.importc: "tls".}: pointer 181 | 182 | when CONFIG_THREAD_RUNTIME_STATS: 183 | ## * Runtime statistics 184 | rt_stats* {.importc: "rt_stats".}: pointer 185 | 186 | # when CONFIG_DEMAND_PAGING_THREAD_STATS: 187 | # ## * Paging statistics 188 | # paging_stats* {.importc: "paging_stats", header: hdr.}: k_mem_paging_stats_t 189 | # arch* {.importc: "arch".}: _thread_arch ## * arch-specifics: must always be at the end 190 | 191 | k_tid_t* = ptr k_thread 192 | -------------------------------------------------------------------------------- /testresults/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"name":"tests/unit_tests/t_nvs_cfg_obj.nim c","category":"pattern","target":"c","action":"run","result":"reExitcodesDiffer","expected":"exitcode: 0","given":"exitcode: 1\n\nOutput:\n\n[Suite] nvs config object\n [OK] essential truths\nCFG name: dac_calib_gain => 31415 \nCFG name: dac_calib_offset => 2718 \nCFG skipping name: %s adc_calib_gain \nCFG skipping name: %s adc_calib_offset \n [OK] basic load\nCFG saving settings \nCFG save setting field: dac_calib_gain(9007) => oldVal=none(int32) -> val=1112 \nCFG save setting field: dac_calib_offset(62141) => oldVal=none(int32) -> val=2222 \nCFG save setting field: adc_calib_gain(13793) => oldVal=none(int32) -> val=0 \nCFG save setting field: adc_calib_offset(46583) => oldVal=none(int32) -> val=0 \n /home/user/modulinos/repos/nephyr/tests/unit_tests/t_nvs_cfg_obj.nim(85, 18): Check failed: fld1Val == 1111\n fld1Val was 1112\n [FAILED] basic store\n","machine":"f837b78137b6","commit":"2f00cb3afcc","branch":"main"}] 3 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | _cache_*/ 2 | test 3 | *-log.txt 4 | !t* 5 | t*.nim 6 | -------------------------------------------------------------------------------- /tests/c_headers/example_mcast.nim: -------------------------------------------------------------------------------- 1 | import 2 | net_private, ipv6 3 | 4 | proc join_coap_multicast_group*(): bool = 5 | var my_addr: in6_addr 6 | var mcast_addr: sockaddr_in6 7 | var ifaddr: ptr net_if_addr 8 | var iface: ptr net_if 9 | var ret: cint 10 | iface = net_if_get_default() 11 | if not iface: 12 | LOG_ERR("Could not get te default interface\n") 13 | return false 14 | var lladdr: ptr in6_addr 15 | ## if (net_addr_pton(AF_INET6, 16 | ## CONFIG_NET_CONFIG_MY_IPV6_ADDR, 17 | ## &my_addr) < 0) { 18 | ## LOG_ERR("Invalid IPv6 address %s", 19 | ## CONFIG_NET_CONFIG_MY_IPV6_ADDR); 20 | ## } 21 | ifaddr = net_if_ipv6_addr_add(iface, addr(my_addr), NET_ADDR_MANUAL, 0) 22 | if not ifaddr: 23 | LOG_ERR("Could not add unicast address to interface") 24 | return false 25 | ifaddr.addr_state = NET_ADDR_PREFERRED 26 | ret = net_ipv6_mld_join(iface, addr(mcast_addr.sin6_addr)) 27 | if ret < 0: 28 | LOG_ERR("Cannot join %s IPv6 multicast group (%d)", 29 | log_strdup(net_sprint_ipv6_addr(addr(mcast_addr.sin6_addr))), ret) 30 | return false 31 | return true 32 | -------------------------------------------------------------------------------- /tests/c_headers/kernel_structs.nim: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2016 Wind River Systems, Inc. 3 | ## 4 | ## SPDX-License-Identifier: Apache-2.0 5 | ## 6 | ## 7 | ## The purpose of this file is to provide essential/minimal kernel structure 8 | ## definitions, so that they can be used without including kernel.h. 9 | ## 10 | ## The following rules must be observed: 11 | ## 1. kernel_structs.h shall not depend on kernel.h both directly and 12 | ## indirectly (i.e. it shall not include any header files that include 13 | ## kernel.h in their dependency chain). 14 | ## 2. kernel.h shall imply kernel_structs.h, such that it shall not be 15 | ## necessary to include kernel_structs.h explicitly when kernel.h is 16 | ## included. 17 | ## 18 | 19 | 20 | var STACK_SENTINEL* {.importc: "STACK_SENTINEL", header: "kernel_structs.h".}: int ## Magic value in lowest bytes of the stack 21 | 22 | var Z_NON_PREEMPT_THRESHOLD* {.importc: "_NON_PREEMPT_THRESHOLD", 23 | header: "kernel_structs.h".}: int ## lowest value of _thread_base.preempt at which a thread is non-preemptible 24 | 25 | var Z_PREEMPT_THRESHOLD* {.importc: "_PREEMPT_THRESHOLD", header: "kernel_structs.h".}: int ## highest value of _thread_base.preempt at which a thread is preemptible 26 | 27 | type 28 | _ready_q* {.importc: "_ready_q", header: "kernel_structs.h", bycopy.} = object 29 | when not CONFIG_SMP: 30 | ## always contains next thread to run: cannot be NULL 31 | var cache* {.importc: "cache", header: "kernel_structs.h".}: ptr k_thread 32 | when CONFIG_SCHED_DUMB: 33 | var runq* {.importc: "runq", header: "kernel_structs.h".}: sys_dlist_t 34 | elif CONFIG_SCHED_SCALABLE: 35 | var runq* {.importc: "runq", header: "kernel_structs.h".}: _priq_rb 36 | elif CONFIG_SCHED_MULTIQ: 37 | var runq* {.importc: "runq", header: "kernel_structs.h".}: _priq_mq 38 | 39 | type 40 | _ready_q_t* = _ready_q 41 | type 42 | _cpu* {.importc: "_cpu", header: "kernel_structs.h", bycopy.} = object 43 | nested* {.importc: "nested".}: uint32 ## nested interrupt count 44 | ## interrupt stack pointer base 45 | irq_stack* {.importc: "irq_stack".}: cstring ## currently scheduled thread 46 | current* {.importc: "current".}: ptr k_thread ## one assigned idle thread per CPU 47 | idle_thread* {.importc: "idle_thread".}: ptr k_thread 48 | when (CONFIG_NUM_METAIRQ_PRIORITIES > 0) and 49 | (CONFIG_NUM_COOP_PRIORITIES > 0): 50 | ## Coop thread preempted by current metairq, or NULL 51 | var metairq_preempted* {.importc: "metairq_preempted", 52 | header: "kernel_structs.h".}: ptr k_thread 53 | when CONFIG_TIMESLICING: 54 | ## number of ticks remaining in current time slice 55 | var slice_ticks* {.importc: "slice_ticks", header: "kernel_structs.h".}: cint 56 | id* {.importc: "id".}: uint8 57 | when CONFIG_SMP: 58 | ## True when _current is allowed to context switch 59 | var swap_ok* {.importc: "swap_ok", header: "kernel_structs.h".}: uint8 60 | arch* {.importc: "arch".}: _cpu_arch ## Per CPU architecture specifics 61 | 62 | type 63 | _cpu_t* = _cpu 64 | type 65 | z_kernel* {.importc: "z_kernel", header: "kernel_structs.h", bycopy.} = object 66 | cpus* {.importc: "cpus".}: array[CONFIG_MP_NUM_CPUS, _cpu] 67 | when CONFIG_PM: 68 | var idle* {.importc: "idle", header: "kernel_structs.h".}: int32 69 | ## Number of ticks for kernel idling 70 | ready_q* {.importc: "ready_q".}: _ready_q ## 71 | ## ready queue: can be big, keep after small fields, since some 72 | ## assembly (e.g. ARC) are limited in the encoding of the offset 73 | ## 74 | when CONFIG_FPU_SHARING: 75 | ## 76 | ## A 'current_sse' field does not exist in addition to the 'current_fp' 77 | ## field since it's not possible to divide the IA-32 non-integer 78 | ## registers into 2 distinct blocks owned by differing threads. In 79 | ## other words, given that the 'fxnsave/fxrstor' instructions 80 | ## save/restore both the X87 FPU and XMM registers, it's not possible 81 | ## for a thread to only "own" the XMM registers. 82 | ## 83 | ## thread that owns the FP regs 84 | var current_fp* {.importc: "current_fp", header: "kernel_structs.h".}: ptr k_thread 85 | when CONFIG_THREAD_MONITOR: 86 | var threads* {.importc: "threads", header: "kernel_structs.h".}: ptr k_thread 87 | ## singly linked list of ALL threads 88 | 89 | type 90 | _kernel_t* = z_kernel 91 | var _kernel* {.importc: "_kernel", header: "kernel_structs.h".}: z_kernel 92 | when CONFIG_SMP: 93 | ## True if the current context can be preempted and migrated to 94 | ## another SMP CPU. 95 | ## 96 | proc z_smp_cpu_mobile*(): bool {.importc: "z_smp_cpu_mobile", 97 | header: "kernel_structs.h".} 98 | var _current_cpu* {.importc: "_current_cpu", header: "kernel_structs.h".}: int 99 | else: 100 | var _current_cpu* {.importc: "_current_cpu", header: "kernel_structs.h".}: int 101 | ## kernel wait queue record 102 | when CONFIG_WAITQ_SCALABLE: 103 | type 104 | _wait_q_t* {.importc: "_wait_q_t", header: "kernel_structs.h", bycopy.} = object 105 | waitq* {.importc: "waitq".}: _priq_rb 106 | 107 | proc z_priq_rb_lessthan*(a: ptr rbnode; b: ptr rbnode): bool {. 108 | importc: "z_priq_rb_lessthan", header: "kernel_structs.h".} 109 | proc Z_WAIT_Q_INIT*(wait_q: untyped) {.importc: "Z_WAIT_Q_INIT", 110 | header: "kernel_structs.h".} 111 | else: 112 | type 113 | _wait_q_t* {.importc: "_wait_q_t", header: "kernel_structs.h", bycopy.} = object 114 | waitq* {.importc: "waitq".}: sys_dlist_t 115 | 116 | proc Z_WAIT_Q_INIT*(wait_q: untyped) {.importc: "Z_WAIT_Q_INIT", 117 | header: "kernel_structs.h".} 118 | ## kernel timeout record 119 | discard "forward decl of _timeout" 120 | type 121 | _timeout_func_t* = proc (t: ptr _timeout) 122 | type 123 | _timeout* {.importc: "_timeout", header: "kernel_structs.h", bycopy.} = object 124 | node* {.importc: "node".}: sys_dnode_t 125 | fn* {.importc: "fn".}: _timeout_func_t 126 | when CONFIG_TIMEOUT_64BIT: 127 | ## Can't use k_ticks_t for header dependency reasons 128 | var dticks* {.importc: "dticks", header: "kernel_structs.h".}: int64 129 | else: 130 | var dticks* {.importc: "dticks", header: "kernel_structs.h".}: int32 131 | -------------------------------------------------------------------------------- /tests/c_headers/net_core.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * @brief Network core definitions 3 | * 4 | * Definitions for networking support. 5 | */ 6 | 7 | /* 8 | * Copyright (c) 2015 Intel Corporation 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | */ 12 | 13 | #ifndef ZEPHYR_INCLUDE_NET_NET_CORE_H_ 14 | #define ZEPHYR_INCLUDE_NET_NET_CORE_H_ 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /** 30 | * @brief Networking 31 | * @defgroup networking Networking 32 | * @{ 33 | * @} 34 | */ 35 | 36 | /** 37 | * @brief Network core library 38 | * @defgroup net_core Network Core Library 39 | * @ingroup networking 40 | * @{ 41 | */ 42 | 43 | /** @cond INTERNAL_HIDDEN */ 44 | 45 | /* Network subsystem logging helpers */ 46 | #ifdef CONFIG_THREAD_NAME 47 | #define NET_DBG(fmt, ...) LOG_DBG("(%s): " fmt, \ 48 | log_strdup(k_thread_name_get(k_current_get())), \ 49 | ##__VA_ARGS__) 50 | #else 51 | #define NET_DBG(fmt, ...) LOG_DBG("(%p): " fmt, k_current_get(), \ 52 | ##__VA_ARGS__) 53 | #endif /* CONFIG_THREAD_NAME */ 54 | #define NET_ERR(fmt, ...) LOG_ERR(fmt, ##__VA_ARGS__) 55 | #define NET_WARN(fmt, ...) LOG_WRN(fmt, ##__VA_ARGS__) 56 | #define NET_INFO(fmt, ...) LOG_INF(fmt, ##__VA_ARGS__) 57 | 58 | #define NET_HEXDUMP_DBG(_data, _length, _str) LOG_HEXDUMP_DBG(_data, _length, _str) 59 | #define NET_HEXDUMP_ERR(_data, _length, _str) LOG_HEXDUMP_ERR(_data, _length, _str) 60 | #define NET_HEXDUMP_WARN(_data, _length, _str) LOG_HEXDUMP_WRN(_data, _length, _str) 61 | #define NET_HEXDUMP_INFO(_data, _length, _str) LOG_HEXDUMP_INF(_data, _length, _str) 62 | 63 | #define NET_ASSERT(cond, ...) __ASSERT(cond, "" __VA_ARGS__) 64 | 65 | /* This needs to be here in order to avoid circular include dependency between 66 | * net_pkt.h and net_if.h 67 | */ 68 | #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \ 69 | defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) 70 | #if !defined(NET_PKT_DETAIL_STATS_COUNT) 71 | #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) 72 | 73 | #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) 74 | #define NET_PKT_DETAIL_STATS_COUNT 4 75 | #else 76 | #define NET_PKT_DETAIL_STATS_COUNT 3 77 | #endif /* CONFIG_NET_PKT_RXTIME_STATS_DETAIL */ 78 | 79 | #else 80 | #define NET_PKT_DETAIL_STATS_COUNT 4 81 | #endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL */ 82 | 83 | #endif /* !NET_PKT_DETAIL_STATS_COUNT */ 84 | #endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || 85 | CONFIG_NET_PKT_RXTIME_STATS_DETAIL */ 86 | 87 | /** @endcond */ 88 | 89 | struct net_buf; 90 | struct net_pkt; 91 | struct net_context; 92 | struct net_if; 93 | 94 | /** 95 | * @brief Net Verdict 96 | */ 97 | enum net_verdict { 98 | /** Packet has been taken care of. */ 99 | NET_OK, 100 | /** Packet has not been touched, other part should decide about its 101 | * fate. 102 | */ 103 | NET_CONTINUE, 104 | /** Packet must be dropped. */ 105 | NET_DROP, 106 | }; 107 | 108 | /** 109 | * @brief Called by lower network stack or network device driver when 110 | * a network packet has been received. The function will push the packet up in 111 | * the network stack for further processing. 112 | * 113 | * @param iface Network interface where the packet was received. 114 | * @param pkt Network packet data. 115 | * 116 | * @return 0 if ok, <0 if error. 117 | */ 118 | int net_recv_data(struct net_if *iface, struct net_pkt *pkt); 119 | 120 | /** 121 | * @brief Send data to network. 122 | * 123 | * @details Send data to network. This should not be used normally by 124 | * applications as it requires that the network packet is properly 125 | * constructed. 126 | * 127 | * @param pkt Network packet. 128 | * 129 | * @return 0 if ok, <0 if error. If <0 is returned, then the caller needs 130 | * to unref the pkt in order to avoid memory leak. 131 | */ 132 | int net_send_data(struct net_pkt *pkt); 133 | 134 | /** @cond INTERNAL_HIDDEN */ 135 | 136 | /* Some helper defines for traffic class support */ 137 | #if defined(CONFIG_NET_TC_TX_COUNT) && defined(CONFIG_NET_TC_RX_COUNT) 138 | #define NET_TC_TX_COUNT CONFIG_NET_TC_TX_COUNT 139 | #define NET_TC_RX_COUNT CONFIG_NET_TC_RX_COUNT 140 | 141 | #if NET_TC_TX_COUNT > NET_TC_RX_COUNT 142 | #define NET_TC_COUNT NET_TC_TX_COUNT 143 | #else 144 | #define NET_TC_COUNT NET_TC_RX_COUNT 145 | #endif 146 | #else /* CONFIG_NET_TC_TX_COUNT && CONFIG_NET_TC_RX_COUNT */ 147 | #define NET_TC_TX_COUNT 0 148 | #define NET_TC_RX_COUNT 0 149 | #define NET_TC_COUNT 0 150 | #endif /* CONFIG_NET_TC_TX_COUNT && CONFIG_NET_TC_RX_COUNT */ 151 | 152 | /* @endcond */ 153 | 154 | /** 155 | * @} 156 | */ 157 | 158 | #ifdef __cplusplus 159 | } 160 | #endif 161 | 162 | #endif /* ZEPHYR_INCLUDE_NET_NET_CORE_H_ */ 163 | -------------------------------------------------------------------------------- /tests/c_headers/net_l2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Intel Corporation. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /** 8 | * @file 9 | * @brief Public API for network L2 interface 10 | */ 11 | 12 | #ifndef ZEPHYR_INCLUDE_NET_NET_L2_H_ 13 | #define ZEPHYR_INCLUDE_NET_NET_L2_H_ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * @brief Network Layer 2 abstraction layer 25 | * @defgroup net_l2 Network L2 Abstraction Layer 26 | * @ingroup networking 27 | * @{ 28 | */ 29 | 30 | struct net_if; 31 | 32 | /** L2 flags */ 33 | /** packed */ 34 | enum net_l2_flags { 35 | /** IP multicast supported */ 36 | NET_L2_MULTICAST = BIT(0), 37 | 38 | /** Do not joint solicited node multicast group */ 39 | NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE = BIT(1), 40 | 41 | /** Is promiscuous mode supported */ 42 | NET_L2_PROMISC_MODE = BIT(2), 43 | 44 | /** Is this L2 point-to-point with tunneling so no need to have 45 | * IP address etc to network interface. 46 | */ 47 | NET_L2_POINT_TO_POINT = BIT(3), 48 | } ; 49 | 50 | /** 51 | * @brief Network L2 structure 52 | * 53 | * Used to provide an interface to lower network stack. 54 | */ 55 | struct net_l2 { 56 | /** 57 | * This function is used by net core to get iface's L2 layer parsing 58 | * what's relevant to itself. 59 | */ 60 | enum net_verdict (*recv)(struct net_if *iface, struct net_pkt *pkt); 61 | 62 | /** 63 | * This function is used by net core to push a packet to lower layer 64 | * (interface's L2), which in turn might work on the packet relevantly. 65 | * (adding proper header etc...) 66 | * Returns a negative error code, or the number of bytes sent otherwise. 67 | */ 68 | int (*send)(struct net_if *iface, struct net_pkt *pkt); 69 | 70 | /** 71 | * This function is used to enable/disable traffic over a network 72 | * interface. The function returns <0 if error and >=0 if no error. 73 | */ 74 | int (*enable)(struct net_if *iface, bool state); 75 | 76 | /** 77 | * Return L2 flags for the network interface. 78 | */ 79 | enum net_l2_flags (*get_flags)(struct net_if *iface); 80 | }; 81 | 82 | // /** @cond INTERNAL_HIDDEN */ 83 | // #define NET_L2_GET_NAME(_name) _net_l2_##_name 84 | // #define NET_L2_DECLARE_PUBLIC(_name) \ 85 | // extern const struct net_l2 NET_L2_GET_NAME(_name) 86 | // #define NET_L2_GET_CTX_TYPE(_name) _name##_CTX_TYPE 87 | 88 | // #ifdef CONFIG_NET_L2_VIRTUAL 89 | // #define VIRTUAL_L2 VIRTUAL 90 | // NET_L2_DECLARE_PUBLIC(VIRTUAL_L2); 91 | // #endif /* CONFIG_NET_L2_DUMMY */ 92 | 93 | // #ifdef CONFIG_NET_L2_DUMMY 94 | // #define DUMMY_L2 DUMMY 95 | // #define DUMMY_L2_CTX_TYPE void* 96 | // NET_L2_DECLARE_PUBLIC(DUMMY_L2); 97 | // #endif /* CONFIG_NET_L2_DUMMY */ 98 | 99 | // #ifdef CONFIG_NET_L2_ETHERNET 100 | // #define ETHERNET_L2 ETHERNET 101 | // NET_L2_DECLARE_PUBLIC(ETHERNET_L2); 102 | // #endif /* CONFIG_NET_L2_ETHERNET */ 103 | 104 | // #ifdef CONFIG_NET_L2_PPP 105 | // #define PPP_L2 PPP 106 | // NET_L2_DECLARE_PUBLIC(PPP_L2); 107 | // #endif /* CONFIG_NET_L2_PPP */ 108 | 109 | // #ifdef CONFIG_NET_L2_IEEE802154 110 | // #define IEEE802154_L2 IEEE802154 111 | // NET_L2_DECLARE_PUBLIC(IEEE802154_L2); 112 | // #endif /* CONFIG_NET_L2_IEEE802154 */ 113 | 114 | // #ifdef CONFIG_NET_L2_BT 115 | // #define BLUETOOTH_L2 BLUETOOTH 116 | // #define BLUETOOTH_L2_CTX_TYPE void* 117 | // NET_L2_DECLARE_PUBLIC(BLUETOOTH_L2); 118 | // #endif /* CONFIG_NET_L2_BT */ 119 | 120 | // #ifdef CONFIG_NET_L2_OPENTHREAD 121 | // #define OPENTHREAD_L2 OPENTHREAD 122 | // NET_L2_DECLARE_PUBLIC(OPENTHREAD_L2); 123 | // #endif /* CONFIG_NET_L2_OPENTHREAD */ 124 | 125 | // #ifdef CONFIG_NET_L2_CANBUS_RAW 126 | // #define CANBUS_RAW_L2 CANBUS_RAW 127 | // #define CANBUS_RAW_L2_CTX_TYPE void* 128 | // NET_L2_DECLARE_PUBLIC(CANBUS_RAW_L2); 129 | // #endif /* CONFIG_NET_L2_CANBUS_RAW */ 130 | 131 | // #ifdef CONFIG_NET_L2_CANBUS 132 | // #define CANBUS_L2 CANBUS 133 | // NET_L2_DECLARE_PUBLIC(CANBUS_L2); 134 | // #endif /* CONFIG_NET_L2_CANBUS */ 135 | 136 | #define NET_L2_INIT(_name, _recv_fn, _send_fn, _enable_fn, _get_flags_fn) \ 137 | const STRUCT_SECTION_ITERABLE(net_l2, \ 138 | NET_L2_GET_NAME(_name)) = { \ 139 | .recv = (_recv_fn), \ 140 | .send = (_send_fn), \ 141 | .enable = (_enable_fn), \ 142 | .get_flags = (_get_flags_fn), \ 143 | } 144 | 145 | #define NET_L2_GET_DATA(name, sfx) _net_l2_data_##name##sfx 146 | 147 | #define NET_L2_DATA_INIT(name, sfx, ctx_type) \ 148 | static ctx_type NET_L2_GET_DATA(name, sfx) __used; 149 | 150 | typedef int (*net_l2_send_t)(const struct device *dev, struct net_pkt *pkt); 151 | 152 | static inline int net_l2_send(net_l2_send_t send_fn, 153 | const struct device *dev, 154 | struct net_if *iface, 155 | struct net_pkt *pkt) 156 | { 157 | net_capture_pkt(iface, pkt); 158 | 159 | return send_fn(dev, pkt); 160 | } 161 | 162 | /** @endcond */ 163 | 164 | /** 165 | * @} 166 | */ 167 | 168 | #ifdef __cplusplus 169 | } 170 | #endif 171 | 172 | #endif /* ZEPHYR_INCLUDE_NET_NET_L2_H_ */ 173 | -------------------------------------------------------------------------------- /tests/c_headers/net_linkaddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Intel Corporation. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /** 8 | * @file 9 | * @brief Public API for network link address 10 | */ 11 | 12 | #ifndef ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_ 13 | #define ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * @brief Network link address library 25 | * @defgroup net_linkaddr Network Link Address Library 26 | * @ingroup networking 27 | * @{ 28 | */ 29 | 30 | /** Maximum length of the link address */ 31 | #ifdef CONFIG_NET_L2_IEEE802154 32 | #define NET_LINK_ADDR_MAX_LENGTH 8 33 | #else 34 | #ifdef CONFIG_NET_L2_PPP 35 | #define NET_LINK_ADDR_MAX_LENGTH 8 36 | #else 37 | #define NET_LINK_ADDR_MAX_LENGTH 6 38 | #endif 39 | #endif 40 | 41 | /** 42 | * Type of the link address. This indicates the network technology that this 43 | * address is used in. Note that in order to save space we store the value 44 | * into a uint8_t variable, so please do not introduce any values > 255 in 45 | * this enum. 46 | */ 47 | /* packed */ 48 | enum net_link_type { 49 | /** Unknown link address type. */ 50 | NET_LINK_UNKNOWN = 0, 51 | /** IEEE 802.15.4 link address. */ 52 | NET_LINK_IEEE802154, 53 | /** Bluetooth IPSP link address. */ 54 | NET_LINK_BLUETOOTH, 55 | /** Ethernet link address. */ 56 | NET_LINK_ETHERNET, 57 | /** Dummy link address. Used in testing apps and loopback support. */ 58 | NET_LINK_DUMMY, 59 | /** CANBUS link address. */ 60 | NET_LINK_CANBUS_RAW, 61 | /** 6loCAN link address. */ 62 | NET_LINK_CANBUS, 63 | } ; 64 | 65 | /** 66 | * @brief Hardware link address structure 67 | * 68 | * Used to hold the link address information 69 | */ 70 | struct net_linkaddr { 71 | /** The array of byte representing the address */ 72 | uint8_t *addr; 73 | 74 | /** Length of that address array */ 75 | uint8_t len; 76 | 77 | /** What kind of address is this for */ 78 | uint8_t type; 79 | }; 80 | 81 | /** 82 | * @brief Hardware link address structure 83 | * 84 | * Used to hold the link address information. This variant is needed 85 | * when we have to store the link layer address. 86 | * 87 | * Note that you cannot cast this to net_linkaddr as uint8_t * is 88 | * handled differently than uint8_t addr[] and the fields are purposely 89 | * in different order. 90 | */ 91 | struct net_linkaddr_storage { 92 | /** What kind of address is this for */ 93 | uint8_t type; 94 | 95 | /** The real length of the ll address. */ 96 | uint8_t len; 97 | 98 | /** The array of bytes representing the address */ 99 | uint8_t addr[NET_LINK_ADDR_MAX_LENGTH]; 100 | }; 101 | 102 | /** 103 | * @brief Compare two link layer addresses. 104 | * 105 | * @param lladdr1 Pointer to a link layer address 106 | * @param lladdr2 Pointer to a link layer address 107 | * 108 | * @return True if the addresses are the same, false otherwise. 109 | */ 110 | static inline bool net_linkaddr_cmp(struct net_linkaddr *lladdr1, 111 | struct net_linkaddr *lladdr2) 112 | { 113 | if (!lladdr1 || !lladdr2) { 114 | return false; 115 | } 116 | 117 | if (lladdr1->len != lladdr2->len) { 118 | return false; 119 | } 120 | 121 | return !memcmp(lladdr1->addr, lladdr2->addr, lladdr1->len); 122 | } 123 | 124 | /** 125 | * 126 | * @brief Set the member data of a link layer address storage structure. 127 | * 128 | * @param lladdr_store The link address storage structure to change. 129 | * @param new_addr Array of bytes containing the link address. 130 | * @param new_len Length of the link address array. 131 | * This value should always be <= NET_LINK_ADDR_MAX_LENGTH. 132 | */ 133 | static inline int net_linkaddr_set(struct net_linkaddr_storage *lladdr_store, 134 | uint8_t *new_addr, uint8_t new_len) 135 | { 136 | if (!lladdr_store || !new_addr) { 137 | return -EINVAL; 138 | } 139 | 140 | if (new_len > NET_LINK_ADDR_MAX_LENGTH) { 141 | return -EMSGSIZE; 142 | } 143 | 144 | lladdr_store->len = new_len; 145 | memcpy(lladdr_store->addr, new_addr, new_len); 146 | 147 | return 0; 148 | } 149 | 150 | /** 151 | * @} 152 | */ 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | 158 | #endif /* ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_ */ 159 | -------------------------------------------------------------------------------- /tests/c_headers/net_timeout.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * @brief Network timer with wrap around 3 | * 4 | * Timer that runs longer than about 49 days needs to calculate wraps. 5 | */ 6 | 7 | /* 8 | * Copyright (c) 2018 Intel Corporation 9 | * Copyright (c) 2020 Nordic Semiconductor ASA 10 | * 11 | * SPDX-License-Identifier: Apache-2.0 12 | */ 13 | 14 | #ifndef ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ 15 | #define ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ 16 | 17 | /** 18 | * @brief Network long timeout primitives and helpers 19 | * @defgroup net_timeout Network long timeout primitives and helpers 20 | * @ingroup networking 21 | * @{ 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** @brief Divisor used to support ms resolution timeouts. 35 | * 36 | * Because delays are processed in work queues which are not invoked 37 | * synchronously with clock changes we need to be able to detect timeouts 38 | * after they occur, which requires comparing "deadline" to "now" with enough 39 | * "slop" to handle any observable latency due to "now" advancing past 40 | * "deadline". 41 | * 42 | * The simplest solution is to use the native conversion of the well-defined 43 | * 32-bit unsigned difference to a 32-bit signed difference, which caps the 44 | * maximum delay at INT32_MAX. This is compatible with the standard mechanism 45 | * for detecting completion of deadlines that do not overflow their 46 | * representation. 47 | */ 48 | #define NET_TIMEOUT_MAX_VALUE ((uint32_t)INT32_MAX) 49 | 50 | /** Generic struct for handling network timeouts. 51 | * 52 | * Except for the linking node, all access to state from these objects must go 53 | * through the defined API. 54 | */ 55 | struct net_timeout { 56 | /** Used to link multiple timeouts that share a common timer infrastructure. 57 | * 58 | * For examples a set of related timers may use a single delayed work 59 | * structure, which is always scheduled at the shortest time to a 60 | * timeout event. 61 | */ 62 | sys_snode_t node; 63 | 64 | /* Time at which the timer was last set. 65 | * 66 | * This usually corresponds to the low 32 bits of k_uptime_get(). */ 67 | uint32_t timer_start; 68 | 69 | /* Portion of remaining timeout that does not exceed 70 | * NET_TIMEOUT_MAX_VALUE. 71 | * 72 | * This value is updated in parallel with timer_start and wrap_counter 73 | * by net_timeout_evaluate(). 74 | */ 75 | uint32_t timer_timeout; 76 | 77 | /* Timer wrap count. 78 | * 79 | * This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that 80 | * have yet to pass. It is also updated along with timer_start and 81 | * wrap_counter by net_timeout_evaluate(). 82 | */ 83 | uint32_t wrap_counter; 84 | }; 85 | 86 | /** @brief Configure a network timeout structure. 87 | * 88 | * @param timeout a pointer to the timeout state. 89 | * 90 | * @param lifetime the duration of the timeout in seconds. 91 | * 92 | * @param now the time at which the timeout started counting down, in 93 | * milliseconds. This is generally a captured value of k_uptime_get_32(). 94 | */ 95 | void net_timeout_set(struct net_timeout *timeout, 96 | uint32_t lifetime, 97 | uint32_t now); 98 | 99 | /** @brief Return the 64-bit system time at which the timeout will complete. 100 | * 101 | * @note Correct behavior requires invocation of net_timeout_evaluate() at its 102 | * specified intervals. 103 | * 104 | * @param timeout state a pointer to the timeout state, initialized by 105 | * net_timeout_set() and maintained by net_timeout_evaluate(). 106 | * 107 | * @param now the full-precision value of k_uptime_get() relative to which the 108 | * deadline will be calculated. 109 | * 110 | * @return the value of k_uptime_get() at which the timeout will expire. 111 | */ 112 | int64_t net_timeout_deadline(const struct net_timeout *timeout, 113 | int64_t now); 114 | 115 | /** @brief Calculate the remaining time to the timeout in whole seconds. 116 | * 117 | * @note This function rounds the remaining time down, i.e. if the timeout 118 | * will occur in 3500 milliseconds the value 3 will be returned. 119 | * 120 | * @note Correct behavior requires invocation of net_timeout_evaluate() at its 121 | * specified intervals. 122 | * 123 | * @param timeout a pointer to the timeout state 124 | * 125 | * @param now the time relative to which the estimate of remaining time should 126 | * be calculated. This should be recently captured value from 127 | * k_uptime_get_32(). 128 | * 129 | * @retval 0 if the timeout has completed. 130 | * @retval positive the remaining duration of the timeout, in seconds. 131 | */ 132 | uint32_t net_timeout_remaining(const struct net_timeout *timeout, 133 | uint32_t now); 134 | 135 | /** @brief Update state to reflect elapsed time and get new delay. 136 | * 137 | * This function must be invoked periodically to (1) apply the effect of 138 | * elapsed time on what remains of a total delay that exceeded the maximum 139 | * representable delay, and (2) determine that either the timeout has 140 | * completed or that the infrastructure must wait a certain period before 141 | * checking again for completion. 142 | * 143 | * @param timeout a pointer to the timeout state 144 | * 145 | * @param now the time relative to which the estimate of remaining time should 146 | * be calculated. This should be recently captured value from 147 | * k_uptime_get_32(). 148 | * 149 | * @retval 0 if the timeout has completed 150 | * @retval positive the maximum delay until the state of this timeout should 151 | * be re-evaluated, in milliseconds. 152 | */ 153 | uint32_t net_timeout_evaluate(struct net_timeout *timeout, 154 | uint32_t now); 155 | 156 | #ifdef __cplusplus 157 | } 158 | #endif 159 | 160 | /** 161 | * @} 162 | */ 163 | 164 | 165 | #endif /* ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ */ 166 | -------------------------------------------------------------------------------- /tests/c_headers/sys_clock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /** 8 | * @file 9 | * @brief Variables needed for system clock 10 | * 11 | * 12 | * Declare variables used by both system timer device driver and kernel 13 | * components that use timer functionality. 14 | */ 15 | 16 | #ifndef ZEPHYR_INCLUDE_SYS_CLOCK_H_ 17 | #define ZEPHYR_INCLUDE_SYS_CLOCK_H_ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /** 32 | * @addtogroup clock_apis 33 | * @{ 34 | */ 35 | 36 | /** 37 | * @brief Tick precision used in timeout APIs 38 | * 39 | * This type defines the word size of the timeout values used in 40 | * k_timeout_t objects, and thus defines an upper bound on maximum 41 | * timeout length (or equivalently minimum tick duration). Note that 42 | * this does not affect the size of the system uptime counter, which 43 | * is always a 64 bit count of ticks. 44 | */ 45 | #ifdef CONFIG_TIMEOUT_64BIT 46 | typedef int64_t k_ticks_t; 47 | #else 48 | typedef uint32_t k_ticks_t; 49 | #endif 50 | 51 | #define K_TICKS_FOREVER ((k_ticks_t) -1) 52 | 53 | /** 54 | * @brief Kernel timeout type 55 | * 56 | * Timeout arguments presented to kernel APIs are stored in this 57 | * opaque type, which is capable of representing times in various 58 | * formats and units. It should be constructed from application data 59 | * using one of the macros defined for this purpose (e.g. `K_MSEC()`, 60 | * `K_TIMEOUT_ABS_TICKS()`, etc...), or be one of the two constants 61 | * K_NO_WAIT or K_FOREVER. Applications should not inspect the 62 | * internal data once constructed. Timeout values may be compared for 63 | * equality with the `K_TIMEOUT_EQ()` macro. 64 | */ 65 | typedef struct { 66 | k_ticks_t ticks; 67 | } k_timeout_t; 68 | 69 | /** 70 | * @brief Compare timeouts for equality 71 | * 72 | * The k_timeout_t object is an opaque struct that should not be 73 | * inspected by application code. This macro exists so that users can 74 | * test timeout objects for equality with known constants 75 | * (e.g. K_NO_WAIT and K_FOREVER) when implementing their own APIs in 76 | * terms of Zephyr timeout constants. 77 | * 78 | * @return True if the timeout objects are identical 79 | */ 80 | #define K_TIMEOUT_EQ(a, b) ((a).ticks == (b).ticks) 81 | 82 | #define Z_TIMEOUT_NO_WAIT ((k_timeout_t) {}) 83 | #if defined(__cplusplus) && ((__cplusplus - 0) < 202002L) 84 | #define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { (t) }) 85 | #else 86 | #define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { .ticks = (t) }) 87 | #endif 88 | #define Z_FOREVER Z_TIMEOUT_TICKS(K_TICKS_FOREVER) 89 | 90 | #ifdef CONFIG_TIMEOUT_64BIT 91 | # define Z_TIMEOUT_MS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ms_to_ticks_ceil64(MAX(t, 0))) 92 | # define Z_TIMEOUT_US(t) Z_TIMEOUT_TICKS((k_ticks_t)k_us_to_ticks_ceil64(MAX(t, 0))) 93 | # define Z_TIMEOUT_NS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ns_to_ticks_ceil64(MAX(t, 0))) 94 | # define Z_TIMEOUT_CYC(t) Z_TIMEOUT_TICKS((k_ticks_t)k_cyc_to_ticks_ceil64(MAX(t, 0))) 95 | #else 96 | # define Z_TIMEOUT_MS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ms_to_ticks_ceil32(MAX(t, 0))) 97 | # define Z_TIMEOUT_US(t) Z_TIMEOUT_TICKS((k_ticks_t)k_us_to_ticks_ceil32(MAX(t, 0))) 98 | # define Z_TIMEOUT_NS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ns_to_ticks_ceil32(MAX(t, 0))) 99 | # define Z_TIMEOUT_CYC(t) Z_TIMEOUT_TICKS((k_ticks_t)k_cyc_to_ticks_ceil32(MAX(t, 0))) 100 | #endif 101 | 102 | /* Converts between absolute timeout expiration values (packed into 103 | * the negative space below K_TICKS_FOREVER) and (non-negative) delta 104 | * timeout values. If the result of Z_TICK_ABS(t) is >= 0, then the 105 | * value was an absolute timeout with the returend expiration time. 106 | * Note that this macro is bidirectional: Z_TICK_ABS(Z_TICK_ABS(t)) == 107 | * t for all inputs, and that the representation of K_TICKS_FOREVER is 108 | * the same value in both spaces! Clever, huh? 109 | */ 110 | #define Z_TICK_ABS(t) (K_TICKS_FOREVER - 1 - (t)) 111 | 112 | /** @} */ 113 | 114 | #ifdef CONFIG_TICKLESS_KERNEL 115 | extern void z_enable_sys_clock(void); 116 | #endif 117 | 118 | #if CONFIG_SYS_CLOCK_EXISTS && \ 119 | (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0) 120 | #error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!" 121 | #endif 122 | 123 | /* number of nsec per usec */ 124 | #define NSEC_PER_USEC 1000U 125 | 126 | /* number of microseconds per millisecond */ 127 | #define USEC_PER_MSEC 1000U 128 | 129 | /* number of milliseconds per second */ 130 | #define MSEC_PER_SEC 1000U 131 | 132 | /* number of microseconds per second */ 133 | #define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC)) 134 | 135 | /* number of nanoseconds per second */ 136 | #define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC)) 137 | 138 | 139 | /* kernel clocks */ 140 | 141 | /* 142 | * We default to using 64-bit intermediates in timescale conversions, 143 | * but if the HW timer cycles/sec, ticks/sec and ms/sec are all known 144 | * to be nicely related, then we can cheat with 32 bits instead. 145 | */ 146 | 147 | #ifdef CONFIG_SYS_CLOCK_EXISTS 148 | 149 | #if CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME || \ 150 | (MSEC_PER_SEC % CONFIG_SYS_CLOCK_TICKS_PER_SEC) || \ 151 | (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC % CONFIG_SYS_CLOCK_TICKS_PER_SEC) 152 | #define _NEED_PRECISE_TICK_MS_CONVERSION 153 | #endif 154 | 155 | #endif 156 | 157 | /* added tick needed to account for tick in progress */ 158 | #define _TICK_ALIGN 1 159 | 160 | /* 161 | * SYS_CLOCK_HW_CYCLES_TO_NS_AVG converts CPU clock cycles to nanoseconds 162 | * and calculates the average cycle time 163 | */ 164 | #define SYS_CLOCK_HW_CYCLES_TO_NS_AVG(X, NCYCLES) \ 165 | (uint32_t)(k_cyc_to_ns_floor64(X) / NCYCLES) 166 | 167 | /** 168 | * 169 | * @brief Return the lower part of the current system tick count 170 | * 171 | * @return the current system tick count 172 | * 173 | */ 174 | uint32_t sys_clock_tick_get_32(void); 175 | 176 | /** 177 | * 178 | * @brief Return the current system tick count 179 | * 180 | * @return the current system tick count 181 | * 182 | */ 183 | int64_t sys_clock_tick_get(void); 184 | 185 | #ifndef CONFIG_SYS_CLOCK_EXISTS 186 | #define sys_clock_tick_get() (0) 187 | #define sys_clock_tick_get_32() (0) 188 | #endif 189 | 190 | uint64_t sys_clock_timeout_end_calc(k_timeout_t timeout); 191 | 192 | #ifdef __cplusplus 193 | } 194 | #endif 195 | 196 | #endif /* ZEPHYR_INCLUDE_SYS_CLOCK_H_ */ 197 | -------------------------------------------------------------------------------- /tests/c_headers/thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #ifndef ZEPHYR_INCLUDE_KERNEL_THREAD_H_ 8 | #define ZEPHYR_INCLUDE_KERNEL_THREAD_H_ 9 | 10 | #ifdef CONFIG_DEMAND_PAGING_THREAD_STATS 11 | #include 12 | #endif 13 | 14 | /** 15 | * @typedef k_thread_entry_t 16 | * @brief Thread entry point function type. 17 | * 18 | * A thread's entry point function is invoked when the thread starts executing. 19 | * Up to 3 argument values can be passed to the function. 20 | * 21 | * The thread terminates execution permanently if the entry point function 22 | * returns. The thread is responsible for releasing any shared resources 23 | * it may own (such as mutexes and dynamically allocated memory), prior to 24 | * returning. 25 | * 26 | * @param p1 First argument. 27 | * @param p2 Second argument. 28 | * @param p3 Third argument. 29 | * 30 | * @return N/A 31 | */ 32 | 33 | #ifdef CONFIG_THREAD_MONITOR 34 | struct __thread_entry { 35 | k_thread_entry_t pEntry; 36 | void *parameter1; 37 | void *parameter2; 38 | void *parameter3; 39 | }; 40 | #endif 41 | 42 | /* can be used for creating 'dummy' threads, e.g. for pending on objects */ 43 | struct _thread_base { 44 | 45 | /* this thread's entry in a ready/wait queue */ 46 | union { 47 | sys_dnode_t qnode_dlist; 48 | struct rbnode qnode_rb; 49 | }; 50 | 51 | /* wait queue on which the thread is pended (needed only for 52 | * trees, not dumb lists) 53 | */ 54 | _wait_q_t *pended_on; 55 | 56 | /* user facing 'thread options'; values defined in include/kernel.h */ 57 | uint8_t user_options; 58 | 59 | /* thread state */ 60 | uint8_t thread_state; 61 | 62 | /* 63 | * scheduler lock count and thread priority 64 | * 65 | * These two fields control the preemptibility of a thread. 66 | * 67 | * When the scheduler is locked, sched_locked is decremented, which 68 | * means that the scheduler is locked for values from 0xff to 0x01. A 69 | * thread is coop if its prio is negative, thus 0x80 to 0xff when 70 | * looked at the value as unsigned. 71 | * 72 | * By putting them end-to-end, this means that a thread is 73 | * non-preemptible if the bundled value is greater than or equal to 74 | * 0x0080. 75 | */ 76 | union { 77 | struct { 78 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 79 | uint8_t sched_locked; 80 | int8_t prio; 81 | #else /* LITTLE and PDP */ 82 | int8_t prio; 83 | uint8_t sched_locked; 84 | #endif 85 | }; 86 | uint16_t preempt; 87 | }; 88 | 89 | #ifdef CONFIG_SCHED_DEADLINE 90 | int prio_deadline; 91 | #endif 92 | 93 | uint32_t order_key; 94 | 95 | #ifdef CONFIG_SMP 96 | /* True for the per-CPU idle threads */ 97 | uint8_t is_idle; 98 | 99 | /* CPU index on which thread was last run */ 100 | uint8_t cpu; 101 | 102 | /* Recursive count of irq_lock() calls */ 103 | uint8_t global_lock_count; 104 | 105 | #endif 106 | 107 | #ifdef CONFIG_SCHED_CPU_MASK 108 | /* "May run on" bits for each CPU */ 109 | uint8_t cpu_mask; 110 | #endif 111 | 112 | void *swap_data; /* data returned by APIs */ 113 | 114 | #ifdef CONFIG_SYS_CLOCK_EXISTS 115 | /* this thread's entry in a timeout queue */ 116 | struct _timeout timeout; 117 | #endif 118 | }; 119 | 120 | typedef struct _thread_base _thread_base_t; 121 | 122 | #if CONFIG_THREAD_STACK_INFO 123 | /* Contains the stack information of a thread */ 124 | struct _thread_stack_info { 125 | /* Stack start - Represents the start address of the thread-writable 126 | * stack area. 127 | */ 128 | uintptr_t start; 129 | 130 | /* Thread writable stack buffer size. Represents the size of the actual 131 | * buffer, starting from the 'start' member, that should be writable by 132 | * the thread. This comprises of the thread stack area, any area reserved 133 | * for local thread data storage, as well as any area left-out due to 134 | * random adjustments applied to the initial thread stack pointer during 135 | * thread initialization. 136 | */ 137 | size_t size; 138 | 139 | /* Adjustment value to the size member, removing any storage 140 | * used for TLS or random stack base offsets. (start + size - delta) 141 | * is the initial stack pointer for a thread. May be 0. 142 | */ 143 | size_t delta; 144 | }; 145 | 146 | typedef struct _thread_stack_info _thread_stack_info_t; 147 | #endif /* CONFIG_THREAD_STACK_INFO */ 148 | 149 | #if CONFIG_USERSPACE 150 | struct _mem_domain_info { 151 | /** memory domain queue node */ 152 | sys_dnode_t mem_domain_q_node; 153 | /** memory domain of the thread */ 154 | struct k_mem_domain *mem_domain; 155 | }; 156 | 157 | #endif /* CONFIG_USERSPACE */ 158 | 159 | #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA 160 | struct _thread_userspace_local_data { 161 | #if CONFIG_ERRNO && !CONFIG_ERRNO_IN_TLS 162 | int errno_var; 163 | #endif 164 | }; 165 | #endif 166 | 167 | #ifdef CONFIG_THREAD_RUNTIME_STATS 168 | struct k_thread_runtime_stats { 169 | /* Thread execution cycles */ 170 | #ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS 171 | timing_t execution_cycles; 172 | #else 173 | uint64_t execution_cycles; 174 | #endif 175 | }; 176 | 177 | typedef struct k_thread_runtime_stats k_thread_runtime_stats_t; 178 | 179 | struct _thread_runtime_stats { 180 | /* Timestamp when last switched in */ 181 | #ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS 182 | timing_t last_switched_in; 183 | #else 184 | uint32_t last_switched_in; 185 | #endif 186 | 187 | k_thread_runtime_stats_t stats; 188 | }; 189 | #endif 190 | 191 | struct z_poller { 192 | bool is_polling; 193 | uint8_t mode; 194 | }; 195 | 196 | /** 197 | * @ingroup thread_apis 198 | * Thread Structure 199 | */ 200 | struct k_thread { 201 | 202 | struct _thread_base base; 203 | 204 | /** defined by the architecture, but all archs need these */ 205 | struct _callee_saved callee_saved; 206 | 207 | /** static thread init data */ 208 | void *init_data; 209 | 210 | /** threads waiting in k_thread_join() */ 211 | _wait_q_t join_queue; 212 | 213 | #if CONFIG_POLL 214 | struct z_poller poller; 215 | #endif 216 | 217 | #if CONFIG_THREAD_MONITOR 218 | /** thread entry and parameters description */ 219 | struct __thread_entry entry; 220 | 221 | /** next item in list of all threads */ 222 | struct k_thread *next_thread; 223 | #endif 224 | 225 | #if CONFIG_THREAD_NAME 226 | /** Thread name */ 227 | char name[CONFIG_THREAD_MAX_NAME_LEN]; 228 | #endif 229 | 230 | #ifdef CONFIG_THREAD_CUSTOM_DATA 231 | /** crude thread-local storage */ 232 | void *custom_data; 233 | #endif 234 | 235 | #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA 236 | struct _thread_userspace_local_data *userspace_local_data; 237 | #endif 238 | 239 | #if CONFIG_ERRNO && !CONFIG_ERRNO_IN_TLS 240 | #ifndef CONFIG_USERSPACE 241 | /** per-thread errno variable */ 242 | int errno_var; 243 | #endif 244 | #endif 245 | 246 | #if CONFIG_THREAD_STACK_INFO 247 | /** Stack Info */ 248 | struct _thread_stack_info stack_info; 249 | #endif /* CONFIG_THREAD_STACK_INFO */ 250 | 251 | #if CONFIG_USERSPACE 252 | /** memory domain info of the thread */ 253 | struct _mem_domain_info mem_domain_info; 254 | /** Base address of thread stack */ 255 | k_thread_stack_t *stack_obj; 256 | /** current syscall frame pointer */ 257 | void *syscall_frame; 258 | #endif /* CONFIG_USERSPACE */ 259 | 260 | 261 | #if CONFIG_USE_SWITCH 262 | /* When using __switch() a few previously arch-specific items 263 | * become part of the core OS 264 | */ 265 | 266 | /** z_swap() return value */ 267 | int swap_retval; 268 | 269 | /** Context handle returned via arch_switch() */ 270 | void *switch_handle; 271 | #endif 272 | 273 | struct k_heap *resource_pool; /** resource pool */ 274 | 275 | #if CONFIG_THREAD_LOCAL_STORAGE 276 | /* Pointer to arch-specific TLS area */ 277 | uintptr_t tls; 278 | #endif /* CONFIG_THREAD_LOCAL_STORAGE */ 279 | 280 | #ifdef CONFIG_THREAD_RUNTIME_STATS 281 | /** Runtime statistics */ 282 | struct _thread_runtime_stats rt_stats; 283 | #endif 284 | 285 | #ifdef CONFIG_DEMAND_PAGING_THREAD_STATS 286 | /** Paging statistics */ 287 | struct k_mem_paging_stats_t paging_stats; 288 | #endif 289 | 290 | struct _thread_arch arch; /** arch-specifics: must always be at the end */ 291 | }; 292 | 293 | typedef struct k_thread _thread_t; 294 | typedef struct k_thread *k_tid_t; 295 | 296 | #endif 297 | -------------------------------------------------------------------------------- /tests/config.nims: -------------------------------------------------------------------------------- 1 | switch("path", "$projectDir/../src") -------------------------------------------------------------------------------- /tests/drivers/config.nims: -------------------------------------------------------------------------------- 1 | 2 | switch("path", "$projectDir/../../src") 3 | -------------------------------------------------------------------------------- /tests/drivers/tgeneral.nim: -------------------------------------------------------------------------------- 1 | import sugar 2 | 3 | import nephyr 4 | import nephyr/times 5 | 6 | proc test_times*() = 7 | # get time ... 8 | let ts_us = micros() 9 | dump(ts_us.repr) 10 | let ts_ms = millis() 11 | dump(ts_ms.repr) 12 | 13 | let res: Millis = delay(100.Millis) 14 | if res.int == 0: 15 | echo "slept for 100 millis" 16 | else: 17 | echo "woke early, remain time to wait: ", res.int 18 | 19 | let res2: Micros = delay(100.Micros) 20 | if res2.int == 0: 21 | echo "slept for 100 micros" 22 | else: 23 | echo "woke early, remain time to wait: ", res2.int 24 | 25 | # variants 26 | # delayMicros(100) 27 | # let res3: bool = delayMicros(100) 28 | # echo "slept full amount: ", res3 29 | 30 | # delayMicros(100) 31 | # let res4: bool = delayMicros(100) 32 | # echo "slept full amount: ", res4 33 | 34 | 35 | 36 | test_times() 37 | -------------------------------------------------------------------------------- /tests/drivers/tgpio.nim: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import nephyr 4 | import nephyr/drivers/gpio 5 | # import nephyr/drivers/Pins as Pins 6 | 7 | const 8 | SLEEP_TIME_MS* = 100 9 | 10 | ## The devicetree node identifier for the "led0" alias. 11 | 12 | var 13 | LED0* = DT_GPIO_LABEL(tok"DT_ALIAS(led0)", tok"gpios") 14 | LED1* = DT_GPIO_LABEL(DT_ALIAS(tok"led1"), tok"gpios") 15 | PIN0* = DT_GPIO_PIN(tok"DT_ALIAS(led0)", tok"gpios") 16 | PIN1* = DT_GPIO_PIN(DT_ALIAS(tok"led0"), tok"gpios") 17 | FLAGS* = DT_GPIO_FLAGS(tok"DT_ALIAS(led0)", tok"gpios") 18 | 19 | proc test_gpio*() = 20 | var pin2 = DT_GPIO_PIN(DT_ALIAS(tok"led0"), tok"gpios") 21 | var dev: ptr device 22 | var led_is_on: bool = true 23 | var ret: cint 24 | dev = device_get_binding(LED0) 25 | if dev == nil: 26 | return 27 | ret = gpio_pin_configure(dev, PIN0, GPIO_OUTPUT_ACTIVE or FLAGS) 28 | ret = gpio_pin_configure(dev, PIN1, GPIO_OUTPUT_ACTIVE or FLAGS) 29 | if ret < 0: 30 | return 31 | while true: 32 | discard gpio_pin_set(dev, PIN1, led_is_on.cint) 33 | discard gpio_pin_set(dev, pin2, led_is_on.cint) 34 | led_is_on = not led_is_on 35 | os.sleep(SLEEP_TIME_MS) 36 | echo("test!\n") 37 | 38 | proc test_pins*() = 39 | assert GPIO_INPUT == Pins.IN 40 | assert GPIO_OUTPUT == Pins.OUT 41 | 42 | let pin10 = initPin(alias"led10", Pins.IN) 43 | echo "pin10: ", repr pin10 44 | 45 | let pin20 = initPin(dt"led20", Pins.OUT) 46 | echo "pin20: ", repr pin20 47 | 48 | pin10.level(1) 49 | pin20.level(0) 50 | 51 | echo "pin10: ", $pin10.level() 52 | echo "pin20: ", $pin20.level() 53 | 54 | let pin30 = initPin(dt"led20", Pins.OUT, tok"vctl1_gpios") 55 | echo "pin30: ", repr pin30 56 | 57 | test_gpio() 58 | test_pins() 59 | -------------------------------------------------------------------------------- /tests/drivers/ti2c.nim: -------------------------------------------------------------------------------- 1 | import nephyr/drivers/i2c 2 | export i2c 3 | import macros 4 | 5 | proc i2c_devptr(): I2cDevice = 6 | let devptr = DEVICE_DT_GET(DT_NODELABEL(tok"i2c1")) 7 | var dev = initI2cDevice(devptr, 0x47.I2cAddr) 8 | result = dev 9 | 10 | 11 | proc test_i2c_devptr() = 12 | var dev = i2c_devptr() 13 | echo "dev: ", repr dev 14 | 15 | proc test_i2c_dev_cstring() = 16 | let devname: cstring = DT_LABEL(DT_ALIAS(tok"i2c0")) 17 | var dev = initI2cDevice(devname, 0x47.I2cAddr) 18 | echo "dev: ", repr dev 19 | 20 | # proc test_i2c_txn_form2() = 21 | # var dev = i2c_devptr() 22 | # dev.transfer( 23 | # {write} = CMD_WRITE, 24 | # {write} = [0x8, 0x7], 25 | # {read, stop} = @[0x8, 0x7], 26 | # {read, restart} = @[0x8, 0x7], 27 | # {read, stop} = [CMD_A, CMD_B], 28 | # ) 29 | 30 | proc test_raw_zephyr_api*() = 31 | ## Setup I2C messages 32 | var dev = i2c_devptr() 33 | var wr_addr = regAddressToBytes(I2cReg8 0x44) 34 | var data = [0x0'u8, 0x0, 0x0] 35 | var rxdata = [0x0'u8, 0x0, 0x0] 36 | 37 | var msgs: array[3, i2c_msg] 38 | ## reg the address to write to 39 | 40 | msgs[0].buf = addr wr_addr[0] 41 | msgs[0].len = wr_addr.lenBytes() 42 | 43 | msgs[0].flags = I2C_MSG_WRITE or I2C_MSG_STOP 44 | 45 | ## Data to be written, and STOP after this. 46 | msgs[1].buf = addr data[0] 47 | msgs[1].len = data.lenBytes() 48 | msgs[1].flags = I2C_MSG_WRITE or I2C_MSG_STOP 49 | 50 | ## Data to be read, and STOP after this. 51 | msgs[2].buf = addr rxdata[0] 52 | msgs[2].len = rxdata.lenBytes() 53 | msgs[2].flags = I2C_MSG_READ or I2C_MSG_STOP 54 | 55 | check: i2c_transfer(dev.bus, addr(msgs[0]), msgs.len().uint8, dev.address.uint16) 56 | 57 | proc test_i2c_do_txn() = 58 | # Examples of generic I2C Api 59 | var dev = i2c_devptr() 60 | var data: array[3, uint8] 61 | var data2 = newSeq[uint8](8) 62 | var someData = [0xE3'u8, 0x01, 0x02] 63 | 64 | # Nim nep1 format 65 | dev.doTransfer( 66 | regWrite(I2cReg16(0x4ffd)), # writes i2c register/command 67 | read(data), # i2c read into array 68 | read(data2), # i2c read into seq 69 | write([0x1'u8, 0x2], I2C_MSG_STOP), # i2c write w/ stop 70 | write(someData, I2C_MSG_STOP), 71 | write(bytes(0x1'u8, 0x2)), 72 | write(bytes(0x1, 0x2), {I2C_MSG_WRITE, I2C_MSG_STOP}), 73 | ) 74 | 75 | echo "got data: ", repr data 76 | echo "got data2: ", repr data2 77 | 78 | test_i2c_devptr() 79 | test_i2c_dev_cstring() 80 | # test_i2c_txn_form2() 81 | when defined(ZephyrDebugMacros): 82 | expandMacros: 83 | test_i2c_do_txn() 84 | else: 85 | test_i2c_do_txn() 86 | -------------------------------------------------------------------------------- /tests/drivers/tspi.nim: -------------------------------------------------------------------------------- 1 | 2 | import nephyr 3 | import nephyr/drivers/spi 4 | 5 | var spi_dev: SpiDevice 6 | 7 | proc spi_devptr(): SpiDevice = 8 | var dev0: SpiDevice = initSpiDevice( 9 | bus = DtSpiDevice(tok"mikrobus_spi"), 10 | frequency = 1_000_000.Hertz, 11 | operation = SPI_WORD_SET(8) or SPI_TRANSFER_MSB or SPI_OP_MODE_MASTER, 12 | cs_ctrl = DtSpiCsDevice(tok"click_spi2", tok"1") 13 | ) 14 | 15 | let cs_ctrl1 = DtSpiCsDevice(tok"click_spi2", tok"1") 16 | 17 | proc spi_setup*() = 18 | var dev0: SpiDevice = initSpiDevice( 19 | bus = DtSpiDevice(tok"mikrobus_spi"), 20 | frequency = 1_000_000.Hertz, 21 | operation = SPI_WORD_SET(8) or SPI_TRANSFER_MSB or SPI_OP_MODE_MASTER, 22 | cs_ctrl = DtSpiCsDevice(tok"click_spi2", tok"1") 23 | ) 24 | 25 | let cs_ctrl1 = DtSpiCsDevice(tok"click_spi2", tok"1") 26 | var dev1: SpiDevice = initSpiDevice( 27 | bus = DEVICE_DT_GET(DT_NODELABEL(tok"mikrobus_spi")), 28 | frequency = 1_000_000.Hertz, 29 | operation = SPI_WORD_SET(8) or SPI_TRANSFER_MSB or SPI_OP_MODE_MASTER, 30 | cs_ctrl = cs_ctrl1 31 | ) 32 | 33 | echo "dev0: ", repr dev0 34 | spi_dev = dev1 35 | 36 | proc spi_raw_zephyr_trx*() = 37 | var 38 | rx_buf = @[0x0'u8, 0x0] 39 | rx_bufs = @[spi_buf(buf: addr rx_buf[0], len: csize_t(sizeof(uint8) * rx_buf.len())) ] 40 | rx_bset = spi_buf_set(buffers: addr(rx_bufs[0]), count: rx_bufs.len().csize_t) 41 | 42 | var 43 | tx_buf = [0x0'u8, ] 44 | tx_bufs = @[spi_buf(buf: addr tx_buf[0], len: csize_t(sizeof(uint8) * tx_buf.len())) ] 45 | tx_bset = spi_buf_set(buffers: addr(tx_bufs[0]), count: tx_bufs.len().csize_t) 46 | 47 | proc spi_do_trxn*() = 48 | # Examples of generic I2C Api 49 | var dev = spi_devptr() 50 | var data: array[3, uint8] 51 | var data2 = newSeq[uint8](8) 52 | var someData: Bytes[4] 53 | 54 | # Nim nep1 format 55 | dev.doTransfers( 56 | read(data), # spi read into array 57 | read(data2), # spi read into seq 58 | write([0x1'u8, 0x2]), # spi write w/ stop 59 | write(someData), 60 | readWrite(someData, [0x1'u8, 0x2]), # i2c write w/ stop 61 | write(bytes(0x1, 0x2)), 62 | ) 63 | 64 | echo "got data: ", repr data 65 | echo "got data2: ", repr data2 66 | 67 | # /* MCP2515 Opcodes */ 68 | const 69 | MCP2515_OPCODE_WRITE {.used.} = 0x02'u8 70 | MCP2515_OPCODE_READ {.used.} = 0x03'u8 71 | MCP2515_OPCODE_BIT_MODIFY {.used.} = 0x05'u8 72 | MCP2515_OPCODE_LOAD_TX_BUFFER {.used.} = 0x40'u8 73 | MCP2515_OPCODE_RTS {.used.} = 0x80'u8 74 | MCP2515_OPCODE_READ_RX_BUFFER {.used.} = 0x90'u8 75 | MCP2515_OPCODE_READ_STATUS {.used.} = 0xA0'u8 76 | MCP2515_OPCODE_RESET {.used.} = 0xC0'u8 77 | 78 | proc mcp2515_cmd_read_reg*(reg_addr: SpiReg8, data: var openArray[uint8]) = 79 | # Examples of generic I2C Api 80 | var dev = spi_devptr() 81 | var cmds = [MCP2515_OPCODE_READ, reg_addr] 82 | 83 | # ===== Raw Zephyr API ===== 84 | var 85 | tx_bufs = @[spi_buf(buf: addr cmds[0], len: csize_t(sizeof(uint8) * cmds.len())) ] 86 | tx_bset = spi_buf_set(buffers: addr(tx_bufs[0]), count: tx_bufs.len().csize_t) 87 | 88 | var 89 | rx_bufs = @[spi_buf(buf: addr data[0], len: csize_t(sizeof(uint8) * data.len())) ] 90 | rx_bset = spi_buf_set(buffers: addr(rx_bufs[0]), count: rx_bufs.len().csize_t) 91 | 92 | check: spi_transceive(dev.bus, addr dev.cfg, addr tx_bset, addr rx_bset) 93 | 94 | # ===== Nephyr API ===== 95 | dev.doTransfers( 96 | write(cmds), # spi read into array 97 | read(data), # spi read into seq 98 | ) 99 | 100 | spi_setup() 101 | spi_raw_zephyr_trx() 102 | spi_do_trxn() 103 | 104 | var data: Bytes[8] 105 | mcp2515_cmd_read_reg(SpiReg 0x32, data) 106 | 107 | -------------------------------------------------------------------------------- /tests/drivers/tspi_c.nim: -------------------------------------------------------------------------------- 1 | import nephyr 2 | import nephyr/drivers/spi 3 | 4 | var 5 | cs_ctrl: spi_cs_control 6 | spi_cfg: spi_config 7 | spi_dev: ptr device 8 | 9 | proc spi_setup*() = 10 | 11 | spi_dev = DEVICE_DT_GET(DT_NODELABEL(tok"mikrobus_spi")) 12 | cs_ctrl = 13 | SPI_CS_CONTROL_PTR_DT(DT_NODELABEL(tok"click_spi2"), tok`2`)[] 14 | 15 | spi_cfg = spi_config( 16 | frequency: 1_000_000'u32, 17 | operation: SPI_WORD_SET(8) or SPI_TRANSFER_MSB or SPI_OP_MODE_MASTER, 18 | cs: addr cs_ctrl) 19 | 20 | 21 | proc spi_read*(): int = 22 | 23 | var 24 | rx_buf = @[0x0'u8, 0x0] 25 | rx_bufs = @[spi_buf(buf: addr rx_buf[0], len: csize_t(sizeof(uint8) * rx_buf.len())) ] 26 | rx_bset = spi_buf_set(buffers: addr(rx_bufs[0]), count: rx_bufs.len().csize_t) 27 | 28 | var 29 | tx_buf = [0x0'u8, ] 30 | tx_bufs = @[spi_buf(buf: addr tx_buf[0], len: csize_t(sizeof(uint8) * tx_buf.len())) ] 31 | tx_bset = spi_buf_set(buffers: addr(tx_bufs[0]), count: tx_bufs.len().csize_t) 32 | 33 | check: spi_transceive(spi_dev, addr spi_cfg, addr tx_bset, addr rx_bset) 34 | 35 | result = joinBytes32[int](rx_buf, 2) 36 | result = 0b0011_1111_1111_1111 and result 37 | 38 | -------------------------------------------------------------------------------- /tests/unit_tests/.gitignore: -------------------------------------------------------------------------------- 1 | _cache_*/ 2 | test 3 | *-log.txt 4 | !t* 5 | t*.nim 6 | t_nvs_cfg_obj 7 | -------------------------------------------------------------------------------- /tests/unit_tests/config.nims: -------------------------------------------------------------------------------- 1 | switch("path", "$projectDir/../../src") 2 | 3 | patchFile("nephyr", "nvs", "nvs_mock") -------------------------------------------------------------------------------- /tests/unit_tests/nvs_mock.nim: -------------------------------------------------------------------------------- 1 | ## Mock for NVS using just a table 2 | 3 | import std/[tables, strformat] 4 | 5 | type 6 | NvsId* = distinct uint16 7 | NvsConfig* = ref object 8 | fs*: Table[NvsId, array[128, byte]] 9 | 10 | proc `==`*(a, b: NvsId): bool {.borrow.} 11 | proc `$`*(a: NvsId): string {.borrow.} 12 | 13 | proc read*[T](nvs: NvsConfig, id: NvsId, item: var T) = 14 | var buf = nvs.fs[id] 15 | copyMem(item.addr, buf[0].addr, item.sizeof()) 16 | 17 | proc read*[T](nvs: NvsConfig, id: NvsId, tp: typedesc[T]): T = 18 | read(nvs, id, result) 19 | 20 | proc write*[T](nvs: NvsConfig, id: NvsId, item: T) = 21 | var buf: array[128, byte] 22 | var val = item 23 | copyMem(buf[0].addr, val.addr, item.sizeof()) 24 | nvs.fs[id] = buf 25 | -------------------------------------------------------------------------------- /tests/unit_tests/t_nvs_cfg_obj.nim: -------------------------------------------------------------------------------- 1 | import std/[tables, strformat] 2 | import unittest 3 | 4 | include nephyr/extras/nvsConfigObj 5 | 6 | type 7 | ExampleConfigs* = object 8 | dac_calib_gain*: int32 9 | dac_calib_offset*: int32 10 | 11 | adc_calib_gain*: float32 12 | adc_calib_offset*: int32 13 | 14 | suite "nvs config object": 15 | 16 | setup: 17 | var nvs = NvsConfig() 18 | 19 | # pre-make fields to simulate flash values 20 | let fld1 = mangleFieldName("dac_calib_gain") 21 | let fld2 = mangleFieldName("dac_calib_offset") 22 | nvs.write(fld1, 31415) 23 | nvs.write(fld2, 2718) 24 | 25 | 26 | test "essential truths": 27 | # give up and stop if this fails 28 | 29 | let id1 = 1234'i32 30 | nvs.write(1.NvsId, id1) 31 | let id1res = nvs.read(1.NvsId, int32) 32 | check id1 == id1res 33 | 34 | test "basic load": 35 | var settings = newConfigSettings(nvs, ExampleConfigs()) 36 | 37 | # check default 0 38 | check settings.values.dac_calib_gain == 0 39 | check settings.values.dac_calib_offset == 0 40 | 41 | # check loaded 42 | settings.loadAll() 43 | check settings.values.dac_calib_gain == 31415 44 | check settings.values.dac_calib_offset == 2718 45 | 46 | test "basic store": 47 | var settings = newConfigSettings(nvs, ExampleConfigs()) 48 | 49 | # check default 0 50 | settings.values.dac_calib_gain = 1111 51 | settings.values.dac_calib_offset = 2222 52 | 53 | # check loaded 54 | settings.saveAll() 55 | 56 | var fld1Val: int32 57 | nvs.read(fld1, fld1Val) 58 | 59 | var fld2Val: int32 60 | nvs.read(fld2, fld2Val) 61 | 62 | check fld1Val == 1111 63 | check fld2Val == 2222 -------------------------------------------------------------------------------- /tests/zephyr_c/config.nims: -------------------------------------------------------------------------------- 1 | 2 | switch("path", "$projectDir/../../src") 3 | -------------------------------------------------------------------------------- /tests/zephyr_c/tkernel.nim: -------------------------------------------------------------------------------- 1 | 2 | import zephyr/zkernel 3 | 4 | assert typeof(k_msleep) is proc 5 | -------------------------------------------------------------------------------- /utils/rpc/.gitignore: -------------------------------------------------------------------------------- 1 | rpc_cli 2 | rpc_server_example 3 | -------------------------------------------------------------------------------- /utils/rpc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | rpc_cli: rpc_cli.nim 3 | nim c --nimblePath:$(HOME)/.nimble/pkgs rpc_cli.nim 4 | 5 | 6 | rpc_server_example: rpc_server_example.nim 7 | nim c --nimblePath:$(HOME)/.nimble/pkgs rpc_server_example.nim 8 | 9 | clean: 10 | rm -Rf rpc_cli rpc_server_example 11 | 12 | -------------------------------------------------------------------------------- /utils/rpc/README.md: -------------------------------------------------------------------------------- 1 | 2 | Rpc server examples: 3 | 4 | ```sh 5 | ./rpc_server_example 6 | ``` 7 | 8 | Example output on startup: 9 | 10 | ``` 11 | createRpcRouter: 1400 12 | starting mpack rpc server: buffer: %s1400 13 | Server: starting 14 | Server: started on port: 5555 15 | ``` 16 | 17 | Example rpc calls: 18 | 19 | ```sh 20 | # add two ints, rpc_cli parses in format 21 | ./rpc_cli call --ip=127.0.0.1 -c:1 --pretty addInt 1 2 22 | 23 | # call rpc with 'raw json args' args, must be wrapped in outer json array 24 | ./rpc_cli call --ip=127.0.0.1 -c:1 --pretty addAll --rawJsonArgs '[[1, 2, 3, 4, 5]]' 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /utils/rpc/nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:orc 2 | --os:linux 3 | -------------------------------------------------------------------------------- /utils/rpc/rpc_server_example.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import json 4 | import strutils 5 | import sequtils 6 | 7 | import nephyr/net/json_rpc/router 8 | 9 | const TAG = "server" 10 | const MaxRpcReceiveBuffer {.intdefine.}: int = 1400 11 | 12 | ## Note: 13 | ## Nim uses `when` compile time constructs 14 | ## these are like ifdef's in C and don't really have an equivalent in Python 15 | ## setting the flags can be done in the Makefile `simplewifi-rpc Makefile 16 | ## for example, to compile the example to use JSON, pass `-d:TcpJsonRpcServer` to Nim 17 | ## the makefile has several example already defined for convenience 18 | ## 19 | # import rpc/rpcsocket_json 20 | import nephyr/net/json_rpc/rpcsocket_mpack 21 | 22 | const VERSION* = staticRead("../VERSION").strip() 23 | 24 | 25 | # Setup RPC Server # 26 | proc run_server*() = 27 | 28 | # Setup an RPC router 29 | var rt = createRpcRouter(MaxRpcReceiveBuffer) 30 | 31 | rpc(rt, "version") do() -> string: 32 | result = VERSION 33 | 34 | rpc(rt, "hello") do(input: string) -> string: 35 | # example: ./rpc_cli --ip:$$IP -c:1 '{"method": "hello", "params": ["world"]}' 36 | result = "Hello " & input 37 | 38 | rpc(rt, "addInt") do(a: int, b: int) -> int: 39 | # example: ./rpc_cli --ip:$$IP -c:1 '{"method": "add", "params": [1, 2]}' 40 | result = a + b 41 | 42 | rpc(rt, "addFloat") do(a: float, b: float) -> float: 43 | # example: ./rpc_cli --ip:$$IP -c:1 '{"method": "add", "params": [1, 2]}' 44 | result = a + b 45 | 46 | rpc(rt, "addAll") do(vals: seq[int]) -> int: 47 | # example: ./rpc_cli --ip:$$IP -c:1 '{"method": "add", "params": [1, 2, 3, 4, 5]}' 48 | echo("run_rpc_server: done: " & repr(addr(vals))) 49 | result = 0 50 | for x in vals: 51 | result += x 52 | 53 | 54 | startRpcSocketServer(Port(5555), router=rt) 55 | 56 | when isMainModule: 57 | run_server() 58 | --------------------------------------------------------------------------------