{"id":20077428,"url":"https://github.com/drogue-iot/drogue-embedded-timer","last_synced_at":"2026-03-10T00:33:33.840Z","repository":{"id":55654831,"uuid":"299692447","full_name":"drogue-iot/drogue-embedded-timer","owner":"drogue-iot","description":null,"archived":false,"fork":false,"pushed_at":"2021-12-23T00:42:07.000Z","size":21,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-01-30T17:53:31.229Z","etag":null,"topics":["embedded","iot","timer"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drogue-iot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-29T17:39:28.000Z","updated_at":"2021-02-03T07:36:32.000Z","dependencies_parsed_at":"2022-08-15T05:40:34.591Z","dependency_job_id":null,"html_url":"https://github.com/drogue-iot/drogue-embedded-timer","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/drogue-iot/drogue-embedded-timer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drogue-iot%2Fdrogue-embedded-timer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drogue-iot%2Fdrogue-embedded-timer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drogue-iot%2Fdrogue-embedded-timer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drogue-iot%2Fdrogue-embedded-timer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drogue-iot","download_url":"https://codeload.github.com/drogue-iot/drogue-embedded-timer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drogue-iot%2Fdrogue-embedded-timer/sbom","scorecard":{"id":356530,"data":{"date":"2025-08-11","repo":{"name":"github.com/drogue-iot/drogue-embedded-timer","commit":"811f4c98761bcf75f7d6d0cc5f27c34f894d8c29"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/15 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T09:44:27.380Z","repository_id":55654831,"created_at":"2025-08-18T09:44:27.380Z","updated_at":"2025-08-18T09:44:27.380Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30318483,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T20:05:46.299Z","status":"ssl_error","status_checked_at":"2026-03-09T19:57:04.425Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["embedded","iot","timer"],"created_at":"2024-11-13T15:08:13.213Z","updated_at":"2026-03-10T00:33:33.815Z","avatar_url":"https://github.com/drogue-iot.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `drogue-embedded-timer`\n\n[![crates.io](https://img.shields.io/crates/v/drogue-embedded-timer.svg)](https://crates.io/crates/drogue-embedded-timer)\n[![docs.rs](https://docs.rs/drogue-embedded-timer/badge.svg)](https://docs.rs/drogue-embedded-timer)\n[![Matrix](https://img.shields.io/matrix/drogue-iot:matrix.org)](https://matrix.to/#/#drogue-iot:matrix.org)\n\n\nWhen writing device drivers against `embedded-hal`, a wall can be hit when attempting to work with `CountDown` timers due to the `Time` associated type.\n\nThe `embedded-time` crate is attempting to homogenous the concept of time, clocks, durations and rates.\nAt this point the various HALs have not adopted `embedded-time`, so this crate provides a simple macro to help accomodate drivers needing a consistent view of timers.\n\n## Converting HAL `CountDown` to `embedded-time`\n\nGeneric drivers should be written in terms of `CountDown` that uses `embedded-time` flavors of time.\n\nApplication writers attempting to provision a concrete instance of the aforementioned drivers can use this macro to convert their HAL's timer into an `embedded-time`-centric `CountDown`.\n\n### Example\n\nUse the `embedded_countdown!(...)` macro to define a new struct that can consume a HAL-specific timer, and wrap it into an `embedded-time` timer.\n\nThe macro takes a few arguments:\n\n1. The name of the struct to create.\n2. The exposed units (usually an `embedded-time` duration) expected by the driver.\n3. The HAL's units expected by the built-in `CountDown` structure being wrapped.\n4. The 1-argument conversion routine to handle the conversion.\n\n```rust\nembedded_countdown!(MsToHertzCountDown,\n                embedded_time::duration::Milliseconds,\n                stm32l4xx_hal::time::Hertz\n                 =\u003e (ms) {\n                        let hz: embedded_time::rate::Hertz = ms.to_rate().unwrap();\n                        stm32l4xx_hal::time::Hertz(hz.0)\n                } );\n```\n\nOnce a structure has been defined, you can then use it:\n\n```rust\nlet mut hal_hz_timer = Timer::tim16(device.TIM16, 1, clocks, \u0026mut rcc.apb2);\nlet mut embedded_ms_timer = MsToHertzCountDown::from(hal_hz_timer);\n```\n\nNow the `embedded_ms_timer` is a `CountDown\u003cTime=embedded_time::duration::Milliseconds\u003e` and is no longer tied to a specific HAL implementation.\n\n## Using straight `embedded-time` clocks and timers:\n\nThis crate provides mechanisms for driving an `embedded-time`-centric `Clock` to be able to create `embedded-time` Timers.\n\nYou decide the precision of clock you want to use, first.\n\nThe available precisions are:\n\n* 1 microsecond\n* 2 microsecond\n* 5 microsecond\n* 10 microseconds\n* 25 microseconds\n* 50 microseconds\n* 100 microseconds\n* 200 microseconds\n* 250 microseconds\n* 500 microseconds\n* 1 millisecond\n* 2 millisecond\n* 5 millisecond\n* 10 milliseconds\n* 25 milliseconds\n* 50 milliseconds\n* 100 milliseconds\n* 200 milliseconds\n* 250 milliseconds\n* 500 milliseconds\n* 1 second\n* 30 seconds\n* 60 seconds\n\nEach clock type has a related _Ticker_ type that must also be used:\n\n```rust\n\nuse drogue_embedded_timer::{\n  MillisecondsClock100,\n  MillisecondsTicker100,\n}\n```\n\nDefine the clock as a static variable:\n\n```rust\nstatic CLOCK: MillisecondsClock100 = MillisecondsClock100::new();\n```\n\nConfigure one of your chip's timers to match the `CLOCK` you selected:\n\n```rust\n// STM32L4xx configuration, yours may vary:\nlet mut tim15 = Timer::tim15(device.TIM15, 100, clocks, \u0026mut rcc.apb2);\n```\n\nEnable the timer as an interrupt source:\n\n```rust\ntim15.listen(Event::TimeOut);\n```\n\nObtain a _ticker_ from the `CLOCK` to be used in the ISR. The `ticker(...)` method takes two arguments:\n\n1. Some object you can use to clear the timeout (otherwise unconstrained).\n2. A function-like thing that can use the object in (1) above, to clear the timeout.\n\n```rust\nlet ticker = CLOCK.ticker(\n               tim15, \n               (|t| { t.clear_interrupt(Event::TimeOut); }) as fn(\u0026mut Timer\u003cTIM15\u003e));\n```\n\nUsing RTIC, you may wish to assign the _ticker_ into the shared resources object:\n\n```rust\nstruct Resources {\n    ticker: MillisecondsTicker100\u003c'static, MillisecondsClock100, Timer\u003cTIM15\u003e, fn(\u0026mut Timer\u003cTIM15\u003e)\u003e,\n    ...\n}\n```\n\nHowever is appropriate, call `tick()` on the ticker each time the ISR fires.\nIn RTIC, it might look similar to:\n\n```rust\n#[task(binds = TIM15, priority = 15, resources = [ticker])]\nfn ticker(mut ctx: ticker::Context) {\n    ctx.resources.ticker.tick();\n}\n```\n\nThe ISR should be relative high priority to ensure time marches on.\n\n# Creating timers\n\nOnce your clock is running and ticking over, you can create as many timers as you desire, using normal `embedded-time` functionality:\n\n```rust\n// effectively a blocking Delay type of action:\nlet my_timer = embedded_time::Timer::new(\u0026CLOCK, Seconds(10u32));\nlet my_timer = my_timer.start().unwrap();\nmy_timer.wait().unwrap();\n```\n\n# Reusable Delays\n\nThis crate also provides functionality similar to Embedded HAL's `DelayMs` and `DelayUs` objects.\nA delay may be directly constructed, or created through a clock's `delay()` factory.\n\n```rust\nlet delay = \u0026CLOCK.delay();\ndelay.delay(Milliseconds(50u32));\n```\n\nOnce a `Delay` has expired, it may be re-used.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrogue-iot%2Fdrogue-embedded-timer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrogue-iot%2Fdrogue-embedded-timer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrogue-iot%2Fdrogue-embedded-timer/lists"}