<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hiroyuki OYAMA</title>
    <description>The latest articles on DEV Community by Hiroyuki OYAMA (@oyama).</description>
    <link>https://dev.to/oyama</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3058316%2F7fe16145-1d8e-427f-88dc-457a07180d9e.jpeg</url>
      <title>DEV Community: Hiroyuki OYAMA</title>
      <link>https://dev.to/oyama</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oyama"/>
    <language>en</language>
    <item>
      <title>Secure Key-Value Store for Raspberry Pi Pico</title>
      <dc:creator>Hiroyuki OYAMA</dc:creator>
      <pubDate>Thu, 17 Apr 2025 08:44:48 +0000</pubDate>
      <link>https://dev.to/oyama/secure-key-value-store-for-raspberry-pi-pico-5jd</link>
      <guid>https://dev.to/oyama/secure-key-value-store-for-raspberry-pi-pico-5jd</guid>
      <description>&lt;p&gt;Stop Hardcoding Secrets: How to Secure Configuration on Raspberry Pi Pico.&lt;/p&gt;

&lt;p&gt;When developing IoT applications using the Raspberry Pi Pico W or Pico 2 W, you often need to handle configuration data such as Wi-Fi SSIDs, passwords, and API tokens.&lt;br&gt;
During early development, it’s tempting to hardcode these values into the source code to get things running quickly. But in many cases, this practice carries over into production devices deployed in the field.&lt;br&gt;
However, are those values truly secure?&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo: How "picotool" + "strings" Exposes Your Secrets
&lt;/h2&gt;

&lt;p&gt;It’s common to embed Wi-Fi settings directly in your code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;wifi_ssid&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"MyHomeWiFi"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;wifi_password&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SuperSecretWiFi123"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After flashing the firmware to your Raspberry Pi Pico, you can extract and inspect it using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;picotool save &lt;span class="nt"&gt;-a&lt;/span&gt; firmware.bin  &lt;span class="c"&gt;# extract firmware from device&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;strings firmware.bin | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; wifi  &lt;span class="c"&gt;# find wifi string&lt;/span&gt;
MyHomeWiFi
SuperSecretWiFi123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, any sensitive data embedded in the firmware can be read as plaintext.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Happens
&lt;/h2&gt;

&lt;p&gt;In embedded systems, constant strings and configuration values are typically placed in the read only data section during compilation, and then written directly to flash memory.&lt;br&gt;
On the Raspberry Pi Pico, this means anyone with physical access and standard tools like picotool can easily retrieve them. In short, unless you take precautions, all embedded data is accessible to anyone.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution: Secure Configuration with pico-kvstore
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;pico-kvstore&lt;/code&gt;, you can securely store configuration data in encrypted form. The setup is straightforward and consists of the following steps:&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1. Reading Configuration in Firmware
&lt;/h3&gt;

&lt;p&gt;pico-kvstore is a key-value storage library with a minimal API consisting of only four operations: set, get, find, and delete. Retrieving Wi-Fi configuration values in firmware looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;kvs_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;kvs_get_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wifi_ssid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;kvs_get_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wifi_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code retrieves encrypted values from storage and automatically decrypts them at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2. Enabling Encrypted Storage in pico-kvstore
&lt;/h3&gt;

&lt;p&gt;pico-kvstore allows flexible storage configuration via the &lt;code&gt;kvs_init()&lt;/code&gt; function. To enable encrypted storage, simply initialize the components as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;kvs_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;blockdevice_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockdevice_flash_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KVSTORE_BANK_OFFSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                 &lt;span class="n"&gt;KVSTORE_BANK_DEFAULT_SIZE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;kvs_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;underlying_kvs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kvs_logkvs_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;kvs_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kvs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kvs_securekvs_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;underlying_kvs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;kvs_assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kvs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference implementation: &lt;a href="https://github.com/oyama/pico-kvstore/blob/main/examples/secure_kvs_init.c" rel="noopener noreferrer"&gt;examples/fs_init_secure.c&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3. Encrypting and Writing Configuration from Host
&lt;/h3&gt;

&lt;p&gt;pico-kvstore comes bundled with a command-line tool called kvstore-util, which allows you to create and edit configuration disk images on the development host. You can specify the key-value pairs and the &lt;code&gt;&amp;lt;SECRETKEY&amp;gt;&lt;/code&gt; directly from the command line to prepare a secure image for deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kvstore-util create &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin
&lt;span class="nv"&gt;$ &lt;/span&gt;kvstore-util &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin &lt;span class="nt"&gt;-k&lt;/span&gt; wifi_ssid &lt;span class="nt"&gt;-v&lt;/span&gt; MyHomeWiFi &lt;span class="nt"&gt;-e&lt;/span&gt; &amp;lt;SECRETKEY&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;kvstore-util &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin &lt;span class="nt"&gt;-k&lt;/span&gt; wifi_password &lt;span class="nt"&gt;-v&lt;/span&gt; SuperSecretWiFi123 &lt;span class="nt"&gt;-e&lt;/span&gt; &amp;lt;SECRETKEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 Note: About &lt;code&gt;&amp;lt;SECRETKEY&amp;gt;&lt;/code&gt;&lt;br&gt;
pico-kvstore derives encryption keys from device-unique identifiers:&lt;br&gt;
Pico(RP2040): &lt;code&gt;flash id&lt;/code&gt;&lt;br&gt;
Pico 2(RP2350): &lt;code&gt;chipid&lt;/code&gt;&lt;br&gt;
You can obtain these values using:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;picotool info &lt;span class="nt"&gt;--device&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Example output:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;flash &lt;span class="nb"&gt;id&lt;/span&gt;: 0xE66358986360212E &lt;span class="c"&gt;# RP2040&lt;/span&gt;
chipid: 0x2287f6ab737e2c05 &lt;span class="c"&gt;# RP2350&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Providing these values as &lt;code&gt;&amp;lt;SECRETKEY&amp;gt;&lt;/code&gt; ensures that each device uses a different encryption key, preventing decrypted reuse across devices.&lt;br&gt;
Additionally, pico-kvstore allows you to define the encryption key source via callback functions, making it possible to use secrets stored in RP2350’s OTP region, for example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 4. Flashing the Encrypted Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;picotool load &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin &lt;span class="nt"&gt;-o&lt;/span&gt; 0x101de000  &lt;span class="c"&gt;# RP2040&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;picotool load &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin &lt;span class="nt"&gt;-o&lt;/span&gt; 0x103de000  &lt;span class="c"&gt;# RP2350&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once written, the firmware can access the secure configuration without modification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Should Encrypt Configuration
&lt;/h2&gt;

&lt;p&gt;Encrypting your configuration provides real, practical benefits in embedded deployments:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Protects Sensitive Information from Physical Access
&lt;/h3&gt;

&lt;p&gt;Unlike plaintext values that can be revealed via tools like strings, encrypted data is unreadable without the key. Even with physical access, attackers cannot easily extract Wi-Fi credentials or API keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Device-Specific Keys Strengthen Security
&lt;/h3&gt;

&lt;p&gt;By deriving encryption keys from hardware-specific identifiers like flash id or chipid, encrypted data on one device cannot be reused on another.&lt;br&gt;
This makes leaked configuration data much less useful to attackers. In addition, the RP2350 supports securely storing secrets in its OTP region, which can only be read by firmware with a valid signature. This enables even stronger protection against unauthorized access to device-specific keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Enables Safe and Flexible Updates
&lt;/h3&gt;

&lt;p&gt;Encrypted configuration files can be safely updated in the field. For example, if a Wi-Fi password changes, you can simply overwrite the config file — no firmware rebuild is necessary.&lt;br&gt;
This makes secure updates and maintenance easier and less error-prone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Secure Configuration Is an Easy Win
&lt;/h2&gt;

&lt;p&gt;Hardcoding secrets in firmware may seem convenient during development, but it introduces serious risks when devices are deployed.&lt;/p&gt;

&lt;p&gt;By using pico-kvstore, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep sensitive values out of the firmware&lt;/li&gt;
&lt;li&gt;Store configuration data in encrypted form&lt;/li&gt;
&lt;li&gt;Use device-unique keys for added protection&lt;/li&gt;
&lt;li&gt;Enable secure, hassle-free configuration updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These benefits can be achieved with minimal changes to your codebase, and are well worth the investment.&lt;br&gt;
Security doesn’t have to be complicated. Sometimes, the most impactful improvements are the smallest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Resources
&lt;/h2&gt;

&lt;p&gt;📦 GitHub repository: &lt;a href="https://github.com/oyama/pico-kvstore" rel="noopener noreferrer"&gt;https://github.com/oyama/pico-kvstore&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All tools and example code mentioned in this article are available in the repository above.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>The Minimal Way to Store Configuration on Raspberry Pi Pico</title>
      <dc:creator>Hiroyuki OYAMA</dc:creator>
      <pubDate>Thu, 17 Apr 2025 08:35:49 +0000</pubDate>
      <link>https://dev.to/oyama/the-minimal-way-to-store-configuration-on-raspberry-pi-pico-1ck8</link>
      <guid>https://dev.to/oyama/the-minimal-way-to-store-configuration-on-raspberry-pi-pico-1ck8</guid>
      <description>&lt;p&gt;Need to store settings like Wi-Fi credentials on Raspberry Pi Pico without a bulky filesystem? Here’s a minimal and reliable solution that works with flash memory directly.&lt;br&gt;
When developing with Raspberry Pi Pico (RP2040), you often need to store configuration data such as Wi-Fi credentials or sensor thresholds. While hardcoding these values into your source code is fine during prototyping, a more flexible solution is preferred for production or multi-device deployments.&lt;br&gt;
A common method is to write data directly to the onboard flash memory. However, flash memory has asymmetric erase and write operations, making it somewhat tricky to handle safely and efficiently.&lt;br&gt;
That’s where &lt;code&gt;pico-kvstore&lt;/code&gt; comes in — a simple, robust option designed specifically to handle flash memory characteristics and support day-to-day configuration storage with ease.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Challenge of Writing Directly to Flash
&lt;/h2&gt;

&lt;p&gt;RP2040 allows storing configuration data directly in flash memory, for example by writing raw bytes or structs to an unused area.&lt;br&gt;
Flash memory updates involve two steps: &lt;em&gt;erase&lt;/em&gt; and &lt;em&gt;program&lt;/em&gt;. Erase is performed in 4KB blocks, while programming (writing) is done in 256-byte chunks. After erasing, memory is filled with &lt;code&gt;0xff&lt;/code&gt;. Programming a value changes &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt; bit, but changing &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; bit requires erasing the entire block.&lt;br&gt;
To efficiently use flash memory while safely handling updates and rewrites, you need a custom algorithm and data structure.&lt;br&gt;
pico-kvstore abstracts away these complexities and provides a safe and user-friendly interface for persistent data storage.&lt;/p&gt;
&lt;h2&gt;
  
  
  Simple and Safe Storage with “pico-kvstore”
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pico-kvstore&lt;/code&gt; is a lightweight key-value store designed to safely and efficiently store configuration or sensor data in RP2040’s flash memory.&lt;br&gt;
It handles the low-level flash constraints internally, exposing a simple API to the user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;kvs_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;KEY&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;kvs_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;KEY&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you only interact with keys and values, internally it uses a log-structured format with wear leveling and crash safety.&lt;br&gt;
For users who don’t need a full filesystem but want safe configuration storage, pico-kvstore is an ideal choice.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing Wi-Fi Settings from the Host
&lt;/h2&gt;

&lt;p&gt;If your device uses Wi-Fi, being able to update SSID and password after deployment can be extremely useful — for example, when reusing the same firmware in different environments.&lt;br&gt;
&lt;code&gt;pico-kvstore&lt;/code&gt; makes it easy to write these settings from your development host and read them back on the device during boot.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Writing Config from the Host
&lt;/h3&gt;

&lt;p&gt;Prepare your configuration files on the host and use a tool to create a pico-kvstore image file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Write Wi-Fi credentials to a kvstore image&lt;/span&gt;
kvstore-util create &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin
kvstore-util &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin &lt;span class="nt"&gt;-k&lt;/span&gt; SSID &lt;span class="nt"&gt;-v&lt;/span&gt; “Home_Wi-Fi”
kvstore-util &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; setting.bin &lt;span class="nt"&gt;-k&lt;/span&gt; PASSWORD &lt;span class="nt"&gt;-v&lt;/span&gt; “Secret Password”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write the generated &lt;code&gt;setting.bin&lt;/code&gt; image file to the Pico’s flash using picotool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Write kvstore image to flash&lt;/span&gt;
picotool load &lt;span class="nt"&gt;--offset&lt;/span&gt; 0x101de000 setting.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Reading Config at Boot
&lt;/h3&gt;

&lt;p&gt;On the firmware side, use &lt;code&gt;kvs_get_str()&lt;/code&gt; to read stored settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;kvs_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kvs_get_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SSID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="n"&gt;kvs_get_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connect_to_wifi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No Wi-Fi config found.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of Separating Configuration from Firmware
&lt;/h2&gt;

&lt;p&gt;By using pico-kvstore, you can decouple your firmware and configuration, leading to several practical advantages:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. No Need to Rebuild or Reflash
&lt;/h3&gt;

&lt;p&gt;You can update settings without touching the firmware, speeding up development and deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Easy Per-Device Configuration
&lt;/h3&gt;

&lt;p&gt;Reuse the same firmware while customizing settings for each device. Ideal for batch provisioning and shipping.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Simpler Testing and Version Control
&lt;/h3&gt;

&lt;p&gt;With code and config separated, it’s easier to manage firmware versions and perform consistent testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;pico-kvstore is easy to integrate into any Pico SDK-based project. Simply pull the code from GitHub and link it in your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clone the Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--recursive&lt;/span&gt; https://github.com/oyama/pico-kvstore.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add to Your CMake Project
&lt;/h3&gt;

&lt;p&gt;Update your CMakeLists.txt as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add_subdirectory(pico-kvstore)
target_link_libraries(your_project PRIVATE
  kvstore
  kvstore_default
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Minimal Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include “kvstore.h”
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;kvs_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;kvs_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kvs_get_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello=%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Flash Storage Area
&lt;/h3&gt;

&lt;p&gt;You can customize the offset and size of the storage area depending on your project. See the repository README for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion — Lightweight Storage for Flexible Operation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pico-kvstore&lt;/code&gt; offers a simple yet powerful solution for configuration persistence on resource-constrained platforms like the RP2040.&lt;br&gt;
This article introduced the library using Wi-Fi settings as a concrete example, highlighting key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A simple API that abstracts away flash memory constraints&lt;/li&gt;
&lt;li&gt;Robust structure with wear leveling and crash tolerance&lt;/li&gt;
&lt;li&gt;Separation of firmware and configuration for operational flexibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IoT devices that require reconfigurable parameters (Wi-Fi, thresholds, etc.)&lt;/li&gt;
&lt;li&gt;Deployments with environment-specific settings&lt;/li&gt;
&lt;li&gt;Applications that don’t need a full filesystem but benefit from structured storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Future improvements may include better host integration tools for editing and inspecting config images. We hope pico-kvstore makes your next Pico project a little more efficient.&lt;/p&gt;

&lt;p&gt;👉 GitHub Repository:&lt;br&gt;
🔗 &lt;a href="https://github.com/oyama/pico-kvstore" rel="noopener noreferrer"&gt;https://github.com/oyama/pico-kvstore&lt;/a&gt;&lt;br&gt;
Try it out and let me know what you build!&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
