{"id":4003,"date":"2020-05-24T15:59:32","date_gmt":"2020-05-24T20:59:32","guid":{"rendered":"https:\/\/dev.iachieved.it\/iachievedit\/?p=4003"},"modified":"2020-05-30T18:50:23","modified_gmt":"2020-05-30T23:50:23","slug":"an-introduction-to-the-hifive-rev-b-and-risc-v","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/an-introduction-to-the-hifive-rev-b-and-risc-v\/","title":{"rendered":"An Introduction to the HiFive1 Rev B and RISC-V"},"content":{"rendered":"<p>Today I&#8217;d like to introduce you to a new development board, the <a href=\"https:\/\/www.sifive.com\/boards\/hifive1-rev-b\">HiFive1 Rev B<\/a>.  Equipped with a <a href=\"https:\/\/sifive.cdn.prismic.io\/sifive%2F3d777659-a0dd-49ed-a011-5bebba17aecf_fe310-g002-ds.pdf\">RISC-V Freedom E310 microcontroller<\/a> and designed with an Arduino Uno &#8220;form factor&#8221;, the HiFive1 Rev B is a neat little board that I hope to learn and develop for.<\/p>\n<figure id=\"attachment_4029\" aria-describedby=\"caption-attachment-4029\" style=\"width: 224px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/hifive1_board.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/hifive1_board.jpg\" alt=\"\" width=\"224\" height=\"320\" class=\"size-full wp-image-4029\" \/><\/a><figcaption id=\"caption-attachment-4029\" class=\"wp-caption-text\">My HiFive1<\/figcaption><\/figure>\n<p>There is a lot of material out there about <a href=\"https:\/\/en.wikipedia.org\/wiki\/RISC-V\">RISC-V<\/a> and how it is going to change the future of CPUs, but what attracted me to it was the notion of a completely <a href=\"https:\/\/en.wikipedia.org\/wiki\/Open_standard\">open standard<\/a> <a href=\"https:\/\/en.wikipedia.org\/wiki\/Instruction_set_architecture\">Instruction Set Architecture (ISA)<\/a>.  That and I think working with new hardware and development environments is cool.<\/p>\n<h2>Getting Started<\/h2>\n<p>The <a href=\"https:\/\/sifive.cdn.prismic.io\/sifive%2F4f5a7851-1b52-463b-a293-f352036bc809_hifive1b-getting-started-guide_v1.1.pdf\">Getting Started Guide<\/a> is crucial to read.  If you&#8217;re anything like me you want to dig in as quickly as possible with as little reading as possible, but trust me, reading the guide first is very useful.<\/p>\n<p>You don&#8217;t get anything but the HiFive1 Rev B board if you&#8217;ve ordered it from <a href=\"https:\/\/www.crowdsupply.com\/sifive\/hifive1-rev-b\">Crowd Supply<\/a> and will need a trusty <a href=\"https:\/\/www.amazon.com\/AmazonBasics-Male-Micro-Cable-Black\/dp\/B07232M876?th=1\">USB-A male to USB-micro-B male cable<\/a>.  This connection can be used for both serial communication and power.  Of course, if you have only a system with USB-C you&#8217;ll need some set of adapters to get to USB micro-B.<\/p>\n<p>For the host platform we will be using a MacBook Pro (Retina, 13-inch, Early 2015) running macOS 10.15 (Catalina).  Hopefully if you&#8217;re reading this with the intention of working on the HiFive1 with your Macbook Pro you&#8217;ll already have <a href=\"https:\/\/www.iterm2.com\/\">the best terminal program ever<\/a> installed, but if you don&#8217;t regular <code>Terminal.app<\/code> works.<\/p>\n<p>Let&#8217;s see our boot screen first:<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/welcome.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/welcome.png\" alt=\"\" width=\"583\" height=\"475\" class=\"aligncenter size-full wp-image-4009\" \/><\/a><\/p>\n<p>To see this boot screen you&#8217;ll need to use a serial terminal program.  macOS is going to present the HiFive as the two USB modem devices in the <code>\/dev<\/code> directory.<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nls -1 \/dev\/cu*\n\/dev\/cu.Bluetooth-Incoming-Port\n\/dev\/cu.usbmodem0009790151821\n\/dev\/cu.usbmodem0009790151823\n<\/pre>\n<p>The first <code>cu.usbmodem<\/code> device presented will be the HiFive1, and my suggestion is to open an iTerm and use <code>screen<\/code> to connect to it.  115200 bps is your speed and the default 8N1 settings should work, so in our case <code>screen \/dev\/cu.usbmodem0009790151821 115200<\/code> is all we had to type in the terminal.<\/p>\n<h2>Time to Develop<\/h2>\n<p>There are several key pieces of software you&#8217;ll need to install on your Mac to begin developing on the HiFive1.<\/p>\n<ul>\n<li>a toolchain (i.e., the compiler, assembler, linker, and associated libraries)<\/li>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/OpenOCD\">OpenOCD On-Chip Debugger<\/a><\/li>\n<li>the Freedom <strong>E<\/strong> SDK<\/li>\n<li>Segger J-Link OB debugger<\/li>\n<\/ul>\n<p>We&#8217;ll take each in turn.<\/p>\n<h3>Installing the Toolchain and OpenOCD<\/h3>\n<p>The reference toolchain is a GNU Embedded Toolchain \u2014 v2019.08.0 and can be downloaded directly from SiFive.  Go to the <a href=\"https:\/\/www.sifive.com\/boards\">Boards<\/a> page, scroll down until you see the section labeled <b>Prebuilt RISC-V GCC Toolchain and Emulator<\/b>.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/toolchain.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/toolchain.png\" alt=\"\" width=\"917\" height=\"513\" class=\"aligncenter size-full wp-image-4013\" \/><\/a>  Download both the GNU toolchain and OpenOCD packages and untar both into a suitable installation location.  I prefer to keep things like this in the <code>\/opt<\/code> directory, so we&#8217;ll do the same here in <code>\/opt\/riscv<\/code>.<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\ncd \/opt\nsudo mkdir riscv\ncd riscv\nsudo tar xzf ~\/Downloads\/riscv-openocd-0.10.0-2019.08.2-x86_64-apple-darwin.tar.gz\nsudo tar xzf ~\/Downloads\/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-apple-darwin.tar.gz\n<\/pre>\n<p>Before going any further ensure that the compiler can run:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\n\/opt\/riscv\/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-apple-darwin\/bin\/riscv64-unknown-elf-gcc --version\n<\/pre>\n<p>You may have received the error message <code>\"riscv64-unknown-elf-gcc\" cannot be opened because the developer cannot be verified.<\/code>.  Now, this may be controversial, but I don&#8217;t hold to my OS telling me what software I can and can&#8217;t run, so let&#8217;s get rid of that silliness with <code>spctl<\/code>:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nsudo spctl --master-disable\n<\/pre>\n<p>Let&#8217;s try again:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\n\/opt\/riscv\/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-apple-darwin\/bin\/riscv64-unknown-elf-gcc --version\nriscv64-unknown-elf-gcc (SiFive GCC 8.3.0-2019.08.0) 8.3.0\nCopyright (C) 2018 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n<\/pre>\n<p>Much better.<\/p>\n<h3>Get the SDK<\/h3>\n<p>We have a HiFive1 board which uses the Freedom E310 chip, thus will want to get the <a href=\"https:\/\/github.com\/sifive\/freedom-e-sdk\">Freedom E SDK<\/a>.  For this I like to keep the SDK in my projects directory.<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\ncd ~\/projects\nmkdir sifive\ngit clone --recursive https:\/\/github.com\/sifive\/freedom-e-sdk.git\n<\/pre>\n<p><b>Note:<\/b>  You must use <code>--recursive<\/code> here to check out all of the required packages.<\/p>\n<p>Now, let&#8217;s compile that first program!<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\ncd ~\/projects\/sifive\/freedom-e-sdk\nmake PROGRAM=hello TARGET=sifive-hifive1-revb\n<\/pre>\n<p>In the top-level directory <code>freedom-e-sdk<\/code> is a set of Makefiles that make it easy to compile and generate an image suitable for uploading to the HiFive1 board.  In this case, <code>PROGRAM<\/code> is the name of a subdirectory in <code>freedom-e-sdk\/software<\/code> and <code>TARGET<\/code> is the board you have.<\/p>\n<p>If this is the first time through you&#8217;re going to see a bunch of gibbersh about Python, pip3, virtualenv, etc:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nmake PROGRAM=hello TARGET=sifive-hifive1-revb\n\/Applications\/Xcode.app\/Contents\/Developer\/usr\/bin\/make -f scripts\/virtualenv.mk virtualenv\npython3 -m venv \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/venv\n. \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/venv\/bin\/activate && \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/venv\/bin\/python3 \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/venv\/bin\/pip install pip==20.0.1\nCollecting pip==20.0.1\n...\n<\/pre>\n<p>And, if you receive an error regarding the C compiler cannot create executables, you need to set your <code>RISCV_PATH<\/code> environment variable to point to the correct toolchain like <code>export RISCV_PATH=\/opt\/riscv\/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-apple-darwin'<\/code>.<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nconfigure: error: in `\/Users\/joe\/projects\/sifive\/freedom-e-sdk\/bsp\/sifive-hifive1-revb\/build\/debug':\nconfigure: error: C compiler cannot create executables\nSee `config.log' for more details\nmake: *** [\/Users\/joe\/projects\/sifive\/freedom-e-sdk\/bsp\/sifive-hifive1-revb\/build\/debug\/Makefile] Error 77\n<\/pre>\n<p>It&#8217;s often a good idea to put the various environment variables in a file such as <code>sifive.env<\/code> and this source the script into your environment.<\/p>\n<p><code>sifive.env<\/code>:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nexport RISCV_PATH=\/opt\/riscv\/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-apple-darwin\nexport TARGET=sifive-hifive1-revb\n<\/pre>\n<p>If everything worked properly you&#8217;ll see at the end something like after compiling.<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\n\/opt\/sifive\/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-apple-darwin\/bin\/riscv64-unknown-elf-objcopy -O ihex \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/software\/hello\/debug\/hello.elf \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/software\/hello\/debug\/hello.hex\n<\/pre>\n<h3>Installing J-Link<\/h3>\n<p>Now, we&#8217;re going to upload this to our board, but we will need the Segger J-Link OB debugger.  If it isn&#8217;t installed you&#8217;ll see something like this when trying to use the <code>upload<\/code> target.<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nscripts\/upload --hex \/Users\/joe\/projects\/sifive\/freedom-e-sdk\/software\/hello\/debug\/hello.hex --jlink JLinkExe\nscripts\/upload: line 37: JLinkExe: command not found\nmake: *** [upload] Error 127\n<\/pre>\n<p>To get J-Link head over to the <a href=\"https:\/\/www.segger.com\/downloads\/jlink\/#J-LinkSoftwareAndDocumentationPack\">download page<\/a> and grab the <b>J-Link Software and Documentation pack for macOS<\/b>.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/jlink.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/jlink.png\" alt=\"\" width=\"1361\" height=\"441\" class=\"aligncenter size-full wp-image-4020\" \/><\/a><\/p>\n<p>Install per the instructions, and once that is done you can go back to your SDK directory and type:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nmake PROGRAM=hello TARGET=sifive-hifive1-revb upload\n<\/pre>\n<p>If everything is installed correctly and the board is attached you&#8217;ll see something like:<\/p>\n<pre class=\"theme:arduino-ide lang:sh decode:true\">\nDownloading file [\/Users\/joe\/projects\/sifive\/freedom-e-sdk\/software\/hello\/debug\/hello.hex]...\nComparing flash   [100%] Done.\nErasing flash     [100%] Done.\nProgramming flash [100%] Done.\nVerifying flash   [100%] Done.\nJ-Link: Flash download: Bank 0 @ 0x20000000: 1 range affected (65536 bytes)\nJ-Link: Flash download: Total time needed: 1.582s (Prepare: 0.076s, Compare: 0.363s, Erase: 0.144s, Program: 0.619s, Verify: 0.363s, Restore: 0.014s)\nO.K.\n<\/pre>\n<p>And that&#8217;s it!  If you have a terminal window with a connection to the serial output of the board you&#8217;ll see <code>Hello, World!<\/code>.<\/p>\n<h2>Your Own C Program<\/h2>\n<p>In the directory <code>freedom-e-sdk<\/code> there is a <code>software<\/code> folder that has an <code>example<\/code> template.  We&#8217;ll use that to create our own ASCII art banner.<\/p>\n<p>Copy the template with something like <code>cp -R software\/empty software\/leo-welcome<\/code> and then edit the <code>software\/leo-welcome\/Makefile<\/code> to change the <code>PROGRAM<\/code> name to <code>leo-welcome<\/code>.  Open <code>main.c<\/code> in the same directory and replace the contents with:<\/p>\n<pre class=\"theme:arduino-ide lang:c decode:true\">\n#include <stdio.h>\nconst char* leo[] = {\n\"   \\\\|\\\\||\",\n\"  -' ||||\/\",\n\" \/7   |||||\/\",\n\"\/    |||||||\/`-.____________\",\n\"\\\\-' |||||||||               `-._\",\n\" -|||||||||||               |` -`.\",\n\"   ||||||               \\\\   |   `\\\\\\\\\",\n\"    |||||\\\\  \\\\______...---\\\\_  \\\\    \\\\\\\\\",\n\"       |  \\\\  \\\\           | \\\\  |    ``-.__--.\",\n\"       |  |\\\\  \\\\         \/ \/ | |       ``---'\",\n\"     _\/  \/_\/  \/      __\/ \/ _| |\",\n\"    (,__\/(,__\/      (,__\/ (,__\/\",\n\"\",\n\"           Somos leones.\",\nNULL\n};\nint main() {\n  printf(\"\\e[1;1H\\e[2J\");\n  for (int i = 0; leo[i] != NULL; i++) {\n    printf(\"\\t\\t%s\\n\",leo[i]);\n  }\n}\n<\/pre>\n<p>Compile and upload with <code>make PROGRAM=leo-welcome TARGET=sifive-hifive1-revb upload<\/code> and behold.<\/p>\n<p><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/somosleones.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2020\/05\/somosleones.png\" alt=\"\" width=\"586\" height=\"313\" class=\"aligncenter size-full wp-image-4024\" \/><\/a><\/p>\n<h2>Some Assembly<\/h2>\n<p>I&#8217;ll be honest, I struggled with this part, but that&#8217;s primarily due to the school of hard knocks with piecing together the <a href=\"https:\/\/github.com\/riscv\/riscv-elf-psabi-doc\/blob\/master\/riscv-elf.md\"><b>calling convention<\/b><\/a> for RISC-V.  Let&#8217;s review a few examples.<\/p>\n<h3>Hello World in RISC-V Assembly<\/h3>\n<p>Again, start off with the <code>example<\/code> folder inside <code>freedom-e-sdk<\/code> with something like<\/p>\n<pree class=\"theme:arduino-ide lang:sh decode:true\">\ncd freedom-e-sdk\ncp -R software\/example software\/helloasm\n<\/pre>\n<p>In this case we&#8217;re going to write Hello World in assembly so delete <code>software\/helloasm\/main.c<\/code> and instead create a file called <code>main.S<\/code> with the following content.<\/p>\n<p><code>main.S<\/code>:<\/p>\n<pre class=\"theme:arduino-ide lang:asm decode:true\">\n.global main\n\nmain:\n  la a0,hellomsg\n  call printf\n  ret\n\n.data\nhellomsg:.asciz \"Hello, world!\\n\"\n<\/pre>\n<p>In RISC-V the <code>a<\/code>-registers will contain our procedure arguments, the procedure here being C <code>printf<\/code>.  We use <code>la<\/code> (load address) to bring the address of the <code>hellomsg<\/code> label into <code>a0<\/code> and then <code>call<\/code> the <code>printf<\/code> function.  All of these, in reality, are pseudoinstructions.<\/p>\n<p>The <code>Makefile<\/code> in the template will pick up files with a <code>.S<\/code> extension, so <code>make PROGRAM=helloasm upload<\/code> will assemble, link, and upload our file to the HiFive1.<\/p>\n<h3>Counting Down<\/h3>\n<p>Finally, let&#8217;s look at a <code>countdown<\/code> routine with a <code>max<\/code> and <code>min<\/code>.  Here things are a bit more complicated as we are going to make use of a <i>prologue<\/i> and <i>epilogue<\/i> in our routine.  The prologue saves the <i>return address<\/i> on the stack, and the epilogue loads the address back into the <b>ra<\/b> register such that the instruction <code>ret<\/code> will branch back to our caller.<\/p>\n<p><code>countdown.S<\/code>:<\/p>\n<pre class=\"theme:arduino-ide lang:asm decode:true\">\n.global countdown\n\ncountdown:\n  \/\/ Prologue\n  addi sp,sp,-4   \/\/ 32-bits to save ra on the stack\n  sw   ra,4(sp)   \/\/ Save\n\n  mv s0,a0 \/\/ s0 - max\n  mv s1,a1 \/\/ s1 - min\n\nloop:\n  blt  s0,s1,end  \/\/ end if s1 > s0\n  la   a0,count   \/\/ set up printf\n  mv   a1,s0\n  call printf\n  addi s0,s0,-1   \/\/ max <- max - 1\n  j    loop       \/\/ do while\n\nend:\n  mv   a0,x0      \/\/ Return value of 0\n\n  \/\/ Epilogue\n  lw   ra,4(sp)   \/\/ Reload ra\n  addi sp,sp,4    \/\/ Give back the stack\n  ret\n\n.data\ncount:.asciz \"%d\\n\"\n<\/pre>\n<p>We can call this function with C like this:<\/p>\n<p><code>main.c<\/code>:<\/p>\n<pre class=\"theme:arduino-ide lang:c decode:true\">\n#include <stdio.h>\n\nvoid countdown(int max, int min);\n\nint main(void) {\n  printf(\"It's the final countdown...\\n\");\n  countdown(10, 0);\n  printf(\"...liftoff!\\n\");\n  return 0;\n}\n<\/pre>\n<p>Compile and upload!<\/p>\n<h1>Good References<\/h1>\n<p>There are a lot of great references on RISC-V, its instruction set architecture, and so on.  I've compiled a few of my favorites here.<\/p>\n<ul>\n<li><a href=\"https:\/\/web.eecs.utk.edu\/~smarz1\/courses\/ece356\/notes\/assembly\/\">RISC-V Assembly Language Computer Systems Architecture by Stephen Marz<\/a><\/li>\n<li><a href=\"https:\/\/inst.eecs.berkeley.edu\/~cs61c\/sp19\/lectures\/lec05.pdf\">Introduction to Assembly Language and RISC-V Instruction Set Architecture<\/a><\/li>\n<li><a href=\"https:\/\/inst.eecs.berkeley.edu\/~cs61c\/resources\/su18_lec\/Lecture7.pdf\">RISC-V Instruction Formats by Steven Ho<\/a><\/li>\n<li><a href=\"https:\/\/inst.eecs.berkeley.edu\/~cs61c\/fa17\/lec\/08\/L08%20CALL%20(1up).pdf\">Running a Program with Krste Asanovic &amp; Randy H. Katz<\/a><\/li>\n<\/ul>\n<h1>Closing Thoughts and What's Next<\/h1>\n<p>That wraps it up for this first look at the SiFive HiFive1 Rev B board.  Of course, we haven't even talked about the ESP32-based wireless capabilities of the board, haven't talked about the <a href=\"https:\/\/sifive.github.io\/freedom-metal-docs\/\">Freedom Metal<\/a> library or any of the stuff that will accelerate our development.  Perhaps that's next!<\/p>\n<p>And, if you've made it this far, you might want to check out our next post on <a href=\"https:\/\/dev.iachieved.it\/iachievedit\/hifive1-rev-b-gpio-pins\/\">exploring the HiFive1 GPIO<\/a> pins.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I&#8217;d like to introduce you to a new development board, the HiFive1 Rev B. Equipped with a RISC-V Freedom E310 microcontroller and designed with an Arduino Uno &#8220;form factor&#8221;, the HiFive1 Rev B is a neat little board that I hope to learn and develop for. There is a lot of material out there [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4029,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,102,101],"tags":[],"class_list":["post-4003","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hacking","category-hifive","category-risc-v"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/4003"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=4003"}],"version-history":[{"count":34,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/4003\/revisions"}],"predecessor-version":[{"id":4073,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/4003\/revisions\/4073"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media\/4029"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=4003"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=4003"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=4003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}