{"id":1932,"date":"2015-12-01T22:56:31","date_gmt":"2015-12-02T04:56:31","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=1932"},"modified":"2022-11-21T11:04:08","modified_gmt":"2022-11-21T17:04:08","slug":"gpio-chip-selects-with-the-beaglebone","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/gpio-chip-selects-with-the-beaglebone\/","title":{"rendered":"GPIO Chip Selects with the BeagleBone"},"content":{"rendered":"<p>In my previous <a href=\"http:\/\/wp.me\/p4aNmq-tE\">post<\/a> I made mention that I could not use GPIO-based <a href=\"https:\/\/en.wikipedia.org\/wiki\/Serial_Peripheral_Interface_Bus\">SPI<\/a> chip selects on the <a href=\"http:\/\/beagleboard.org\/BLACK\">BeagleBone Black<\/a> <i>with<\/i> the default <a href=\"http:\/\/processors.wiki.ti.com\/index.php\/AM_McSpi\">McSPI<\/a> driver (what you are using if you&#8217;re opening <code>\/dev\/spidev<\/code>.  The exact quote I had run across (much to my chagrin at the time) was<\/p>\n<blockquote><p>\nIncidentally, the spi-omap2-mcspi.c driver does not support a GPIO as a chip select.\n<\/p><\/blockquote>\n<p>Well, fortunately, a little persistence paid off (I confess, I can be stubborn at times), and I found <a href=\"https:\/\/lkml.org\/lkml\/2015\/5\/23\/144\">this patch<\/a> from <a href=\"https:\/\/twitter.com\/QwertyEmbedded\">Michael Welling<\/a> that adds GPIO chip select support to the <code>spi-omap2-mcspi.c<\/code> driver.<\/p>\n<p>As I mentioned in the <a href=\"\">article<\/a> on using the 4-slot <a href=\"http:\/\/www.mikroe.com\/click\/mikrobus-cape\/\">mikroBUS cape<\/a> I was using a workaround to lower the chip select by hand.  With Linux 4.3 and <i>one additional patch<\/i> you no longer need it.  I&#8217;ve included everything in the <a href=\"https:\/\/github.com\/iachievedit\/BBB-420mA\/\">BBB-420mA<\/a> repository on the <code>linux-4.3<\/code> branch, but wanted to share some additional tips for those looking to work with the <code>cs-gpios<\/code> tag in DTS files.<\/p>\n<h3>Declare your Pins<\/h3>\n<p>The snippet below cannot be taken out of context from the larger <a href=\"https:\/\/github.com\/iachievedit\/BBB-420mA\/blob\/linux-4.3\/BB-SPICAPE-01-00A0.dts\n\">DTS overlay<\/a>, but illustrates that we put our GPIO chip select pin in the same group as the rest of the SPI1 pins.<\/p>\n<pre class=\"crayon:false\">\n    bb_spi1_pins: pinmux_bb_spi1_pins {\n    pinctrl-single,pins = <\n      0x190 0x33    \/* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 *\/\n      0x194 0x33    \/* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 *\/\n      0x198 0x13    \/* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 *\/\n      0x19c 0x13    \/* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 *\/\n      0x164 0x12    \/* eCAP0_in_PWM0_out.spi1_cs1 OUTPUT_PULLUP | MODE2 *\/\n      0x098 0x17    \/* P8 10 gpio2_4.spi1_cs2 OUTPUT_PULLUP | MODE7 *\/\n      >;\n      };\n<\/pre>\n<p>In particular the &#8220;magic&#8221; <code>0x098 0x17<\/code> refers to P8.10 on the Black (and actually the <code>0x098<\/code> refers to the pin and the <code>0x17<\/code> refers to the settings, which in this case we want OUTPUT_PULLUP and MODE7), which is gpio68 in <code>\/sys\/class\/gpio<\/code>.  Another name for it, which we&#8217;ll see below, is <code><&#038;gpio2 4 0><\/code>.  <i>So<\/i> many ways are referring to the same thing.  No wonder it gets confusing.<\/p>\n<p>Next, let&#8217;s revisit our DTS for SPI1 on the Black:<\/p>\n<pre class=\"crayon:false\">\n  fragment@1 {\n    target = <&#038;spi1>;   \/* spi1 is numbered correctly *\/\n    __overlay__ {\n      status = \"okay\";\n      pinctrl-names = \"default\";\n      pinctrl-0 = <&#038;bb_spi1_pins>;\n\n#address-cells = <1>;\n#size-cells = <0>;\n\n      cs-gpios = <0>, <0>, <&#038;gpio2 4 0>;\n\n      spi1@0 {\n#address-cells = <1>;\n#size-cells = <0>;\n    compatible = \"spidev\";\n    reg = <0>;\n    spi-max-frequency = <16000000>;\n    spi-cpol;\n    spi-cpha;          \n      };\n\n      spi1@1 {\n#address-cells = <1>;\n#size-cells = <0>;\n    compatible = \"spidev\";\n    reg = <1>;\n    spi-max-frequency = <16000000>;\n    spi-cpol;\n    spi-cpha;\n      };\n\n      spi1@2 {\n#address-cells = <1>;\n#size-cells = <0>;\n    compatible = \"spidev\";\n    reg = <2>;\n    spi-max-frequency = <16000000>;\n    spi-cpol;\n    spi-cpha;\n      };\n    };\n  };\n<\/pre>\n<p>The <a href=\"https:\/\/www.kernel.org\/doc\/Documentation\/devicetree\/bindings\/spi\/spi-bus.txt\">SPI bus documentation<\/a> is a <i>little<\/i> unclear, but the format for the <code>cs-gpios<\/code> tag is:<\/p>\n<pre class=\"crayon:false\">\n<b>cs-gpios = <\/b> <b><<\/b><i>GPIO<\/i><b>><\/b>|<b><0><\/b><b>,<\/b> <b><<\/b><i>GPIO<\/i><b>><\/b>|<b><0><\/b><b>,<\/b> ...<b>,<\/b> <b><<\/b><i>GPIO<\/i><b>><\/b>|<b><0><\/b><b>;<\/b>\n<\/pre>\n<p>where<\/p>\n<ul>\n<li><b><0><\/b> means &#8220;use the default pin&#8221; for this chip select\n<li><i>GPIO<\/i> is expanded to something like <code>&gpio 4 0<\/code> to identify the gpio pin\n<\/ul>\n<p>So in our example, the line<\/p>\n<pre class=\"crayon:false\">\ncs-gpios = <0>, <0>, <&#038;gpio2 4 0>;\n<\/pre>\n<p>in the DTS overlay is telling the <a href=\"http:\/\/lxr.free-electrons.com\/source\/drivers\/spi\/spi-omap2-mcspi.c\">OMAP SPI driver<\/a> that SPI1 chip select 0 (or CS0 you will see on the BeagleBone Black <a href=\"http:\/\/elinux.org\/images\/b\/bf\/2_SPI_Ports.PNG\">SPI pinouts<\/a>) will use its default pin assignment, chip select 1 will <i>also<\/i> use its default pin assignment, and chip select <i>2<\/i> will use <code><&#038;gpio2 4 0><\/code>, which as we said, is P8.10, aka GPIO 68.  If you&#8217;re confused as to why I want to use P8.10, that&#8217;s because on the mikroBUS cape the clickboard in slot 4 has the chip select line running to P8.10 on the Black.<\/p>\n<figure id=\"attachment_1963\" aria-describedby=\"caption-attachment-1963\" style=\"width: 384px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/12\/host4_chipselect.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/12\/host4_chipselect.png\" alt=\"Host 4 Chip Select is P8.10\" width=\"384\" height=\"384\" class=\"size-full wp-image-1963\" \/><\/a><figcaption id=\"caption-attachment-1963\" class=\"wp-caption-text\">Host 4 Chip Select is P8.10<\/figcaption><\/figure>\n<pre class=\"crayon:false\">\n           CS0     CS1       CS2\n         default default    P8.10\n            |       |         |\n            |       |         |\n            v       v         v\ncs-gpios = <0>,    <0>, <&#038;gpio 2 4 0>;\n<\/pre>\n<p>See the <a href=\"https:\/\/www.kernel.org\/doc\/Documentation\/devicetree\/bindings\/gpio\/gpio.txt\">GPIO overlay structure<\/a> for details on the naming structure for GPIO pins, keeping in mind that &#8220;<i>Exact meaning of each specifier cell is controller specific, and must be documented in the device tree binding for the device.<\/i>&#8221;  This is another way of saying that the structure of the GPIO names aren&#8217;t necessarily the same between the BeagleBone Black and say, a Raspberry Pi.<\/p>\n<h3>Get onto Linux 4.3<\/h3>\n<p>I want to make sure it&#8217;s absolutely clear, you need to be on Linux 4.3 on your BeagleBone Black for anything below to work properly!  The following are quick instructions that, as of the time of this writing (November 30, 2015), should get you a Black that&#8217;s good to go.<\/p>\n<p>First, start off with a latest Debian Jessie image from the <a href=\"http:\/\/elinux.org\/Beagleboard:BeagleBoneBlack_Debian#Jessie_Snapshot_lxqt\">BeagleBone Black images<\/a> page.  In my case I&#8217;m going to use the <a href=\"https:\/\/rcn-ee.com\/rootfs\/bb.org\/testing\/2015-11-29\/lxqt-4gb\/BBB-eMMC-flasher-debian-8.2-lxqt-4gb-armhf-2015-11-29-4gb.img.xz\">2015-11-29 Debian 8.2 Flasher<\/a> image which will flash my BeagleBone.  For details on how to use a flasher image with a BeagleBone, see <a href=\"https:\/\/learn.adafruit.com\/beaglebone-black-installing-operating-systems\/flashing-the-beaglebone-black\">these instructions<\/a>.<\/p>\n<p>Once you&#8217;ve flashed the Black, upgrade the kernel to latest 4.3 release candidate (for the BeagleBone), which, as of this writing, was 4.3.0-rc7-bone1.  Upgrading is quite easy:<\/p>\n<pre class=\"crayon:false\">\napt-get update\napt-get install -y linux-image-4.3.0-rc7-bone1\n<\/pre>\n<p>You&#8217;ll probably see something like:<\/p>\n<pre class=\"crayon:false\">\nSetting up linux-image-4.3.0-rc7-bone1 (1jessie) ...\nError! Error! Your kernel headers for kernel 4.3.0-rc7-bone1 cannot be found.\nYour kernel headers for kernel 4.3.0-rc7-bone1 cannot be found.\nPlease install the linux-headers-4.3.0-rc7-bone1 package,\nPlease install the linux-headers-4.3.0-rc7-bone1 package,\nor use the --kernelsourcedir option to tell DKMS where it's located\nor use the --kernelsourcedir option to tell DKMS where it's located\nError! Your kernel headers for kernel 4.3.0-rc7-bone1 cannot be found.\nPlease install the linux-headers-4.3.0-rc7-bone1 package,\nor use the --kernelsourcedir option to tell DKMS where it's located\nupdate-initramfs: Generating \/boot\/initrd.img-4.3.0-rc7-bone1\nzz-uenv_txt: Updating \/boot\/uEnv.txt [uname_r=4.3.0-rc7-bone1]\n<\/pre>\n<p>Ignore the warnings and reboot!<\/p>\n<h3>Getting the Kernel Source<\/h3>\n<p>Unfortunately, having the 4.3 kernel image on your BeagleBone isn&#8217;t enough; you&#8217;ll have to patch the spi-omap2 driver, and while I&#8217;d love to say it is a piece of cake, well, let&#8217;s just say its a bit of a <a href=\"http:\/\/www.food.com\/recipe\/traditional-8-layer-doberge-cake-372685\">doberge cake<\/a> (pronounced &#8220;doebash&#8221;).<\/p>\n<p>I <i>highly<\/i> recommend this be done on an ARM system such as a <a href=\"http:\/\/www.wandboard.org\/buy\">Wandboard Quad<\/a>, or soon-to-be-released <a href=\"http:\/\/www.elinux.org\/Beagleboard:BeagleBoard-X15\">BeagleBoard X15<\/a>.  You can also accomplish this with a cross-compiling environment though it is a bit more cumbersome.  We&#8217;re going to assume you&#8217;re compiling with a native ARM system, and then look at how to cross-compile in another installment.<\/p>\n<p>To get started, on a sufficiently sized filesystem (>4G free space), let&#8217;s get Robert C. Nelson&#8217;s awesome <a href=\"https:\/\/github.com\/RobertCNelson\/bb-kernel\"><code>bb-kernel<\/code><\/a> repository:<\/p>\n<pre class=\"crayon:false\">\nroot@beagleboard-x15.local:\/mnt\/sd# git clone https:\/\/github.com\/RobertCNelson\/bb-kernel\n<\/pre>\n<p>Since we are going to compile the module for a 4.3-rc7-bone1 kernel, let&#8217;s check out against that tag in the repository.<\/p>\n<pre class=\"crayon:false\">\nroot@beagleboard-x15.local:\/mnt\/sd\/bb-kernel# git checkout 4.3-rc7-bone1\nNote: checking out '4.3-rc7-bone1'.\n...\nHEAD is now at 1f00cb4... 4.3-rc7-bone1 release\n<\/pre>\n<p>This repository provides a great out-of-the-box script to check out the Linux source tree and build everything to make a bootstrapped BeagleBoard kernel, but we want to skip a lot of steps and just build our SPI driver.  So you will want to edit the <code>build_kernel.sh<\/code> script here and comment out everything starting with the <code>AUTO_BUILD<\/code> <code>if<\/code> statement:<\/p>\n<pre class=\"lang:sh\">\n#if [ ! \"${AUTO_BUILD}\" ] ; then\n#        make_menuconfig\n#fi\n#make_kernel\n#make_modules_pkg\n#make_firmware_pkg\n#if grep -q dtbs \"${DIR}\/KERNEL\/arch\/arm\/Makefile\"; then\n#       make_dtbs_pkg\n#fi\n#echo \"-----------------------------\"\n#echo \"Script Complete\"\n#echo \"${KERNEL_UTS}\" > kernel_version\n#echo \"eewiki.net: [user@localhost:~$ export kernel_version=${KERNEL_UTS}]\"\n#echo \"-----------------------------\"\n<\/pre>\n<p>If you read through the script you&#8217;ll see that it checks out the Linux source tree from the appropriate git repository and also patches it for building against the BeagleBone Black.  If you didn&#8217;t comment anything out it would keep running and build the kernel, modules, create a deployment package, etc.  We don&#8217;t need that here.<\/p>\n<p>Run the <i>modified<\/i> <code>build_kernel.sh<\/code> script.  This still may take some time (~20 minutes) as it checks out everything, applies patches, etc.<\/p>\n<p>Before we build our module we want to apply this patch from <a href=\"https:\/\/twitter.com\/QwertyEmbedded\">Michael Welling<\/a> which fixes an issue with trying to claim the GPIO-based chip select line twice:<\/p>\n<pre>\n--- a\/drivers\/spi\/spi-omap2-mcspi.c\n+++ b\/drivers\/spi\/spi-omap2-mcspi.c\n@@ -1025,6 +1025,16 @@ static int omap2_mcspi_setup(struct spi_device *spi)\n        spi->controller_state = cs;\n        \/* Link this to context save list *\/\n        list_add_tail(&cs->node, &ctx->cs);\n+\n+       if (gpio_is_valid(spi->cs_gpio)) {\n+           ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));\n+           if (ret) {\n+               dev_err(&spi->dev, \"failed to request gpio\\n\");\n+               return ret;\n+           }\n+           gpio_direction_output(spi->cs_gpio,\n+                    !(spi->mode & SPI_CS_HIGH));\n+       }\n    }\n \n    if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) {\n@@ -1033,15 +1043,6 @@ static int omap2_mcspi_setup(struct spi_device *spi)\n            return ret;\n    }\n \n-   if (gpio_is_valid(spi->cs_gpio)) {\n-       ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));\n-       if (ret) {\n-           dev_err(&spi->dev, \"failed to request gpio\\n\");\n-           return ret;\n-       }\n-       gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));\n-   }\n-\n    ret = pm_runtime_get_sync(mcspi->dev);\n    if (ret < 0)\n        return ret;\n<\/pre>\n<p>Make sure you are in the <code>KERNEL<\/code> directory which was checked out by running <code>build_kernel.sh<\/code>:<\/p>\n<pre class=\"crayon:false\">\nroot@beagleboard-x15.local:\/mnt\/sd\/bb-kernel # cd KERNEL\nroot@beagleboard-x15.local:\/mnt\/sd\/bb-kernel\/KERNEL # wget http:\/\/dev.iachieved.it\/downloads\/spi-omap2-mcspi.c.patch\nroot@beagleboard-x15.local:\/mnt\/sd\/bb-kernel\/KERNEL # git apply spi-omap2-mcspi.c.patch\n<\/pre>\n<p>If you run <code>git diff<\/code> now you'll see the diff generated by application of the patch.<\/p>\n<p>Before we can recompile our module we need <code>Module.symvers<\/code> file from the Linux headers package (pro tip:  we wouldn't need the Linux headers package from <code>Module.symvers<\/code> if we had built the kernel ourselves, but we're skipping all of that and building a single module).  In the <code>KERNEL<\/code> directory:<\/p>\n<pre class=\"crayon:false\">\nroot@BeagleBoard-X15:\/mnt\/sd\/bb-kernel\/KERNEL# apt-get install -y linux-headers-4.3.0-rc7-bone1\nroot@BeagleBoard-X15:\/mnt\/sd\/bb-kernel\/KERNEL# cp \/usr\/src\/linux-headers-4.3.0-rc7-bone1\/Module.symvers .\n<\/pre>\n<p>Now!  Let's recompile our SPI modules! <i>Three<\/i> <code>make<\/code> steps are necessary:  <code>prepare<\/code>, <code>modules_prepare<\/code> and <code>modules M=drivers\/spi<\/code>:<\/p>\n<pre class=\"crayon:false\">\nroot@BeagleBoard-X15:\/mnt\/sd\/bb-kernel\/KERNEL# make prepare\n...\nroot@BeagleBoard-X15:\/mnt\/sd\/bb-kernel\/KERNEL# make modules_prepare\n...\nroot@BeagleBoard-X15:\/mnt\/sd\/bb-kernel\/KERNEL# make modules M=drivers\/spi\n  CC [M]  drivers\/spi\/spi-dln2.o\n  CC [M]  drivers\/spi\/spi-omap2-mcspi.o\n  Building modules, stage 2.\n  MODPOST 2 modules\n  CC      drivers\/spi\/spi-dln2.mod.o\n  LD [M]  drivers\/spi\/spi-dln2.ko\n  CC      drivers\/spi\/spi-omap2-mcspi.mod.o\n  LD [M]  drivers\/spi\/spi-omap2-mcspi.ko\n<\/pre>\n<p>Now let's copy our newly built spi-omap2-driver.ko module over to the BeagleBone Black:<\/p>\n<pre class=\"crayon:false\">\n\nroot@BeagleBoard-X15:\/mnt\/sd\/bb-kernel\/KERNEL# scp drivers\/spi\/spi-omap2-mcspi.ko root@192.168.1.106:\/lib\/modules\/4.3.0-rc7-bone1\/kernel\/drivers\/spi\/\nspi-omap2-mcspi.ko                            100%   21KB  21.4KB\/s   00:00\n<\/pre>\n<h3>Loading the Overlay<\/h3>\n<p>Recall from the previous <a href=\"http:\/\/wp.me\/p4aNmq-tE\">tutorial<\/a> you will need to compile and install the overlay into <code>\/lib\/firmware<\/code>.  Assuming you've done this (see the previous post for details) and your <code>\/boot\/uEnv.txt<\/code> is in order, load the overlay and then try the <code>transmitReceive420.js<\/code> script in the <code>linux-4.3<\/code> branch of the BBB-420mA repository.<\/p>\n<p>Without a patched spi-omap2 module you would expect to see:<\/p>\n<pre class=\"crayon:false\">\n\/root\/BBB-420mA\/node_modules\/spi\/spi.js:65\n    return this._spi.open(this.device);\n                     ^\n\nTypeError: Unable to set SPI_IOC_WR_MODE\n    at TypeError (native)\n    at Spi.open (\/root\/BBB-420mA\/node_modules\/spi\/spi.js:65:22)\n...\n<\/pre>\n<p>With the updated SPI module:<\/p>\n<pre class=\"crayon:false\">\nroot@beaglebone:~\/BBB-420mA# node transmitReceive420.js 7 14\nMilliamps:                7\nOutput to Transmitter:  1417.8125\nInput from Receiver:    1405\nMillamps:               6.937784262\nMilliamps:                14\nOutput to Transmitter:  2859.375\nInput from Receiver:    2870\nMillamps:               14.051592792\n<\/pre>\n<p>This script was run with a fully populated mikroBUS cape and 4 clickboards!  Two 4-20mA transmitters and two 4-20mA receivers.  The transmitter in slot 2 is looped to the receiver in slot 1.  Likewise, the transmitter in slot 3 is looped to the receiver in slot 4.<\/p>\n<figure id=\"attachment_1967\" aria-describedby=\"caption-attachment-1967\" style=\"width: 287px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/12\/loadedclick.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2015\/12\/loadedclick.jpg\" alt=\"4 SPI Clickboards!\" width=\"287\" height=\"480\" class=\"size-full wp-image-1967\" \/><\/a><figcaption id=\"caption-attachment-1967\" class=\"wp-caption-text\">4 SPI Clickboards!<\/figcaption><\/figure>\n<h2>Getting the Code<\/h2>\n<p>Everything for this tutorial is on the <code>linux-4.3<\/code> branch of the <a href=\"https:\/\/github.com\/iachievedit\/BBB-420mA\/tree\/linux-4.3\">BBB-420mA<\/a> repository.  I highly suggest you look at the README and review the instructions there.  There are admittedly a lot of moving parts involved here:  compiling overlays, adjusting <code>uEnv.txt<\/code>, understanding SPI and chip select, 4-20mA clickboards, compiling kernel modules, and oh, NodeJS too!  Hopefully though when you Google <i>gpio chip select on beaglebone<\/i> you'll find your way here and enjoy the read.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post I made mention that I could not use GPIO-based SPI chip selects on the BeagleBone Black with the default McSPI driver (what you are using if you&#8217;re opening \/dev\/spidev. The exact quote I had run across (much to my chagrin at the time) was Incidentally, the spi-omap2-mcspi.c driver does not support [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,22],"tags":[],"class_list":["post-1932","post","type-post","status-publish","format-standard","hentry","category-beaglebone","category-hacking"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1932"}],"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=1932"}],"version-history":[{"count":40,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1932\/revisions"}],"predecessor-version":[{"id":4597,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1932\/revisions\/4597"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=1932"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=1932"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=1932"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}