{"id":2160,"date":"2023-12-03T06:10:40","date_gmt":"2023-12-03T06:10:40","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2160"},"modified":"2023-12-03T06:10:42","modified_gmt":"2023-12-03T06:10:42","slug":"working-with-stm32-and-external-flash-w25qxx-part3-writing-data","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2160","title":{"rendered":"Working with STM32 and External Flash W25QXX Part3: Writing data"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"436\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/145104325.png.webp\" alt=\"\" class=\"wp-image-2161\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/145104325.png.webp 600w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/145104325.png-300x218.webp 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/145104325.png-400x291.webp 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/145104325.png-250x182.webp 250w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure><\/div>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=2151\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=2151\" target=\"_blank\">here<\/a>), we saw how to read from a sector and get the required data. <\/p>\n\n\n\n<p>In this guide, we shall see how to erase a sector, write the new values.<\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Steps required to write to W25QXX.<\/li><li>Enable\/Disable write.<\/li><li>Sector erase.<\/li><li>Write to a page.<\/li><li>Header file update.<\/li><li>Main code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Steps Required to Write to Flash:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>First, we need to check the length of the data to be written to the flash and calculate how many sectors will be used according to the size and the offset.<\/li><li>Enable the write <\/li><li>After calculating the number of sectors to be written, we shall erase those sectors since W25QXX doesn&#8217;t allow to write a sector with value other than 0xFF.<\/li><li>After erasing the sector, we shall write the new data starting.<\/li><li>Finally disable write.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Enable \/ Disable Write:<\/h2>\n\n\n\n<p>In order to enable the write, need to send enable write command as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Set CS pin to Low.<\/li><li>Write Enable Command.<\/li><li>Set CS pin to high<\/li><\/ul>\n\n\n\n<p>As shown in the figure:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"841\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-841x1024.png\" alt=\"\" class=\"wp-image-2162\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-841x1024.png 841w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-246x300.png 246w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-768x935.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-1262x1536.png 1262w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-1150x1400.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-750x913.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-400x487.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM-250x304.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.15.28\u202fAM.png 1556w\" sizes=\"(max-width: 841px) 100vw, 841px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, enable and disable write functions as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">static void write_enable (void)\n{\n\tuint8_t tData = 0x06;  \/\/ enable write\n\tW25QXX_CS_LOW();\n\tSPI1_Transmit(&amp;tData, 1);\n\tW25QXX_CS_HIGH();\n\tdelay(5);  \/\/ 5ms delay\n}\n\nstatic void write_disable(void)\n{\n\tuint8_t tData = 0x04;  \/\/ disable write\n\tW25QXX_CS_LOW();\n\tSPI1_Transmit(&amp;tData, 1);\n\tW25QXX_CS_HIGH();\n\tdelay(5);  \/\/ 5ms delay\n}\n<\/pre><\/div>\n\n\n\n<p>The functions are declared as static since only this source file needs those functions.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Sector Erase:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The figure shows the architecture of W25QXX:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"922\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-922x1024.png\" alt=\"\" class=\"wp-image-2163\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-922x1024.png 922w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-270x300.png 270w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-768x853.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-1383x1536.png 1383w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-1150x1277.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-750x833.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-400x444.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM-250x278.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.32.42\u202fAM.png 1556w\" sizes=\"(max-width: 922px) 100vw, 922px\" \/><\/figure>\n\n\n\n<p>In case of W25Q32, there is 64 blocks, each block contains 15 sectors of 4KB, within each sector, there is 16 pages each page is 256 byte in length.<\/p>\n\n\n\n<p>Hence, in order to update single element of the page, we need to erase the entire 4KB of sector.<\/p>\n\n\n\n<p>Hence, declare the following function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void W25QXX_Erase_Sector (uint16_t sectore)<\/pre><\/div>\n\n\n\n<p>The function will take sector number as argument and returns nothing.<\/p>\n\n\n\n<p>Declare local buffer of byte to be transmitted over SPI which will hold the erase sector command and the address:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t tData[6];<\/pre><\/div>\n\n\n\n<p>Calculate the address:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint32_t memAddr = sectore*16*256;   \/\/ Each sector contains 16 pages * 256 bytes<\/pre><\/div>\n\n\n\n<p>Enable write:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">write_enable();<\/pre><\/div>\n\n\n\n<p>Write the sector erase command and the address:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tif (NumberOfSector&lt;512)   \/\/ Chip Size&lt;256Mb\n\t{\n\t\ttData[0] = 0x20;  \/\/ Erase sector\n\t\ttData[1] = (memAddr&gt;&gt;16)&amp;0xFF;  \/\/ MSB of the memory Address\n\t\ttData[2] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\ttData[3] = (memAddr)&amp;0xFF; \/\/ LSB of the memory Address\n\n\t\tW25QXX_CS_LOW();\n\t\tSPI1_Transmit(tData, 4);\n\t\tW25QXX_CS_HIGH();\n\t}\n\telse  \/\/ we use 32bit memory address for chips &gt;= 256Mb\n\t{\n\t\ttData[0] = 0x21;  \/\/ ERASE Sector with 32bit address\n\t\ttData[1] = (memAddr&gt;&gt;24)&amp;0xFF;\n\t\ttData[2] = (memAddr&gt;&gt;16)&amp;0xFF;\n\t\ttData[3] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\ttData[4] = memAddr&amp;0xFF;\n\n\t\tW25QXX_CS_LOW();  \/\/ pull the CS LOW\n\t\tSPI1_Transmit(tData, 5);\n\t\tW25QXX_CS_HIGH();  \/\/ pull the HIGH\n\t}<\/pre><\/div>\n\n\n\n<p>Give a delay according to the AC characteristics:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"42\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-1024x42.png\" alt=\"\" class=\"wp-image-2164\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-1024x42.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-300x12.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-768x32.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-1536x63.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-1150x47.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-750x31.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-400x16.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM-250x10.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-8.46.29\u202fAM.png 1948w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since it will take 200ms to erase the sector, to be sure, we shall use 300ms delay:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">delay(300);  \/\/ 200ms delay for sector erase (300ms to be sure)<\/pre><\/div>\n\n\n\n<p>Finally, disable write:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">write_disable();<\/pre><\/div>\n\n\n\n<p>The entire function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void W25QXX_Erase_Sector (uint16_t sectore)\n{\n\tuint8_t tData[6];\n\tuint32_t memAddr = sectore*16*256;   \/\/ Each sector contains 16 pages * 256 bytes\n\n\twrite_enable();\n\n\tif (NumberOfSector&lt;512)   \/\/ Chip Size&lt;256Mb\n\t{\n\t\ttData[0] = 0x20;  \/\/ Erase sector\n\t\ttData[1] = (memAddr&gt;&gt;16)&amp;0xFF;  \/\/ MSB of the memory Address\n\t\ttData[2] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\ttData[3] = (memAddr)&amp;0xFF; \/\/ LSB of the memory Address\n\n\t\tW25QXX_CS_LOW();\n\t\tSPI1_Transmit(tData, 4);\n\t\tW25QXX_CS_HIGH();\n\t}\n\telse  \/\/ we use 32bit memory address for chips &gt;= 256Mb\n\t{\n\t\ttData[0] = 0x21;  \/\/ ERASE Sector with 32bit address\n\t\ttData[1] = (memAddr&gt;&gt;24)&amp;0xFF;\n\t\ttData[2] = (memAddr&gt;&gt;16)&amp;0xFF;\n\t\ttData[3] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\ttData[4] = memAddr&amp;0xFF;\n\n\t\tW25QXX_CS_LOW();  \/\/ pull the CS LOW\n\t\tSPI1_Transmit(tData, 5);\n\t\tW25QXX_CS_HIGH();  \/\/ pull the HIGH\n\t}\n\n\tdelay(300);  \/\/ 200ms delay for sector erase (300ms to be sure)\n\n\twrite_disable();\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Write to a Page:<\/h2>\n\n\n\n<p>Declare the following function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void W25QXX_Write(uint32_t page, uint16_t offset, uint8_t *data, uint32_t size)<\/pre><\/div>\n\n\n\n<p>The function will take the following arguments:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Page, which is the page number.<\/li><li>Offset, which is which the distance from the start of the page.<\/li><li>Pointer to buffer that hold the data to be written.<\/li><li>Size of the data to be written.<\/li><\/ul>\n\n\n\n<p>Declare a local buffer with size of 266 which will be enough to hold the 256 byte of data and the commands.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t tData[266];<\/pre><\/div>\n\n\n\n<p>Calculate the start page, end of the page and how many pages are needed:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tuint32_t startPage = page;\n\tuint32_t endPage  = startPage + ((size+offset-1)\/256);\n\tuint32_t numPages = endPage-startPage+1;<\/pre><\/div>\n\n\n\n<p>Calculate the needed sectors:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tuint16_t startSector  = startPage\/16;\n\tuint16_t endSector  = endPage\/16;\n\tuint16_t numSectors = endSector-startSector+1;<\/pre><\/div>\n\n\n\n<p>Erase the sectors:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tfor (uint16_t i=0; i&lt;numSectors; i++)\n\t{\n\t\tW25QXX_Erase_Sector(startSector++);\n\t}\n<\/pre><\/div>\n\n\n\n<p>Declare a local variable to track the data:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint32_t dataPosition = 0;<\/pre><\/div>\n\n\n\n<p>Write the data:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">for (uint32_t i=0; i&lt;numPages; i++)\n\t{\n\t\tuint32_t memAddr = (startPage*256)+offset;\n\t\tuint16_t bytesremaining  = bytestowrite(size, offset);\n\t\tuint32_t indx = 0;\n\n\t\twrite_enable();\n\n\t\tif (NumberOfSector&lt;512)   \/\/ Chip Size&lt;256Mb\n\t\t{\n\t\t\ttData[0] = 0x02;  \/\/ page program\n\t\t\ttData[1] = (memAddr&gt;&gt;16)&amp;0xFF;  \/\/ MSB of the memory Address\n\t\t\ttData[2] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\t\ttData[3] = (memAddr)&amp;0xFF; \/\/ LSB of the memory Address\n\n\t\t\tindx = 4;\n\t\t}\n\n\t\telse \/\/ we use 32bit memory address for chips &gt;= 256Mb\n\t\t{\n\t\t\ttData[0] = 0x12;  \/\/ page program with 4-Byte Address\n\t\t\ttData[1] = (memAddr&gt;&gt;24)&amp;0xFF;  \/\/ MSB of the memory Address\n\t\t\ttData[2] = (memAddr&gt;&gt;16)&amp;0xFF;\n\t\t\ttData[3] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\t\ttData[4] = (memAddr)&amp;0xFF; \/\/ LSB of the memory Address\n\n\t\t\tindx = 5;\n\t\t}\n\n\t\tuint16_t bytestosend  = bytesremaining + indx;\n\n\t\tfor (uint16_t i=0; i&lt;bytesremaining; i++)\n\t\t{\n\t\t\ttData[indx++] = data[i+dataPosition];\n\t\t}\n\n\t\tif (bytestosend &gt; 200)\n\t\t{\n\t\t\tW25QXX_CS_LOW();\n\t\t\tSPI1_Transmit(tData, 100);\n\t\t\tSPI1_Transmit(tData+100, bytestosend-100);\n\t\t\tW25QXX_CS_HIGH();\n\t\t}\n\n\t\telse\n\t\t{\n\t\t\tW25QXX_CS_LOW();\n\t\t\tSPI1_Transmit(tData, bytestosend);\n\t\t\tW25QXX_CS_HIGH();\n\t\t}\n\n\t\tstartPage++;\n\t\toffset = 0;\n\t\tsize = size-bytesremaining;\n\t\tdataPosition = dataPosition+bytesremaining;\n\n\t\tdelay(5);\n\t\twrite_disable();\n\n\t}<\/pre><\/div>\n\n\n\n<p>The steps as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Step through all the pages using for loop.<\/li><li>Within the for loop:<\/li><li>Get the starting address.<\/li><li>Get the remaining bytes using the following function:<\/li><\/ul>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">static uint32_t bytestowrite (uint32_t size, uint16_t offset)\n{\n\tif ((size+offset)&lt;256) return size;\n\telse return 256-offset;\n}<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>Set Indx to zero.<\/li><li>Check the memory size if it is less than 256Mb or bigger.<\/li><li>Send the page program command 0x02 for less than 25Mb or page program with 32-bit address of 0x12.<\/li><li>Set the indx to 4 or 5 according to the memory size.<\/li><li>Get the bytes to be send.<\/li><li>Fill the buffer.<\/li><li>Check the size of the data, if it it more than 200, send it in certain way, if it less, in other way.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"618\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-1024x618.png\" alt=\"\" class=\"wp-image-2165\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-1024x618.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-300x181.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-768x464.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-1536x927.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-1150x694.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-750x453.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-400x241.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM-250x151.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-03-at-9.03.20\u202fAM.png 1948w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>Update the tracking variables.<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li>Delay by 5ms to ensure data is written.<\/li><li>Disable the write.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the write function as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void W25QXX_Write(uint32_t page, uint16_t offset, uint8_t *data, uint32_t size)\n{\n\tuint8_t tData[266];\n\tuint32_t startPage = page;\n\tuint32_t endPage  = startPage + ((size+offset-1)\/256);\n\tuint32_t numPages = endPage-startPage+1;\n\n\tuint16_t startSector  = startPage\/16;\n\tuint16_t endSector  = endPage\/16;\n\tuint16_t numSectors = endSector-startSector+1;\n\tfor (uint16_t i=0; i&lt;numSectors; i++)\n\t{\n\t\tW25QXX_Erase_Sector(startSector++);\n\t}\n\n\t\n\n\t\/\/ write the data\n\tfor (uint32_t i=0; i&lt;numPages; i++)\n\t{\n\t\tuint32_t memAddr = (startPage*256)+offset;\n\t\tuint16_t bytesremaining  = bytestowrite(size, offset);\n\t\tuint32_t indx = 0;\n\n\t\twrite_enable();\n\n\t\tif (NumberOfSector&lt;512)   \/\/ Chip Size&lt;256Mb\n\t\t{\n\t\t\ttData[0] = 0x02;  \/\/ page program\n\t\t\ttData[1] = (memAddr&gt;&gt;16)&amp;0xFF;  \/\/ MSB of the memory Address\n\t\t\ttData[2] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\t\ttData[3] = (memAddr)&amp;0xFF; \/\/ LSB of the memory Address\n\n\t\t\tindx = 4;\n\t\t}\n\n\t\telse \/\/ we use 32bit memory address for chips &gt;= 256Mb\n\t\t{\n\t\t\ttData[0] = 0x12;  \/\/ page program with 4-Byte Address\n\t\t\ttData[1] = (memAddr&gt;&gt;24)&amp;0xFF;  \/\/ MSB of the memory Address\n\t\t\ttData[2] = (memAddr&gt;&gt;16)&amp;0xFF;\n\t\t\ttData[3] = (memAddr&gt;&gt;8)&amp;0xFF;\n\t\t\ttData[4] = (memAddr)&amp;0xFF; \/\/ LSB of the memory Address\n\n\t\t\tindx = 5;\n\t\t}\n\n\t\tuint16_t bytestosend  = bytesremaining + indx;\n\n\t\tfor (uint16_t i=0; i&lt;bytesremaining; i++)\n\t\t{\n\t\t\ttData[indx++] = data[i+dataPosition];\n\t\t}\n\n\t\tif (bytestosend &gt; 200)\n\t\t{\n\t\t\tW25QXX_CS_LOW();\n\t\t\tSPI1_Transmit(tData, 100);\n\t\t\tSPI1_Transmit(tData+100, bytestosend-100);\n\t\t\tW25QXX_CS_HIGH();\n\t\t}\n\n\t\telse\n\t\t{\n\t\t\tW25QXX_CS_LOW();\n\t\t\tSPI1_Transmit(tData, bytestosend);\n\t\t\tW25QXX_CS_HIGH();\n\t\t}\n\n\t\tstartPage++;\n\t\toffset = 0;\n\t\tsize = size-bytesremaining;\n\t\tdataPosition = dataPosition+bytesremaining;\n\n\t\tdelay(5);\n\t\twrite_disable();\n\n\t}\n}\n\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Update the Header File:<\/h2>\n\n\n\n<p>Open W25QXX.h header file and include the following two functions:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\/*\n * @brief This function will write to W25QXX.\n * @param sector is the sector number of the flash\n * @param offset is the offset of the memory location to be read.\n * @param *rData is a pointer to buffer that will hold the data to be written.\n * @param size if the data to be written.\n * @return nothing\n *\n * *\/\n\nvoid W25QXX_Write(uint32_t page, uint16_t offset, uint8_t *data, uint32_t size);\n\n\/*\n * @brief This function will erase a sectore from W25QXX.\n * @param sector is the sector number of the flash\n * @return nothing\n * *\/\nvoid W25QXX_Erase_Sector (uint16_t sector);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Main code.<\/h2>\n\n\n\n<p>In main.c file:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;delay.h&quot;\n#include &quot;SPI1.h&quot;\n#include &quot;W25QXX.h&quot;\n#include &quot;stdlib.h&quot;\n\nuint32_t W25QXX_ID;\n#define W25Q32_ID\t(uint32_t)0xEF4016\n\nuint8_t rxData[10];\nuint8_t txData[10];\n\n\nint main(void)\n{\tdelay_init(16000000);\n\tsrand(millis());\n\tSPI1_Pins_Init();\n\tW25QXX_CS_Pins_Init();\n\tSPI1_Config();\n\n\tW25QXX_NumberOfSector(64);\n\tW25QXX_Reset();\n\tdelay(100);\n\n\n\n\twhile(1)\n\t{\n\t\tW25QXX_ID=W25QXX_ReadID();\n\n\t\t\/*If the ID is matched read the data*\/\n\t\tif(W25QXX_ID==W25Q32_ID)\n\t\t{\n\n\t\t\tfor (int i=0;i&lt;10;i++)\n\t\t\t{\n\t\t\t\ttxData[i]=rand() % 255;\n\t\t\t}\n\n\n\t\t\tW25QXX_Write(0,0,txData,10);\n\n\t\t\t\/*Write the data*\/\n\n\t\t\tW25QXX_Read(0,0,rxData,10);\n\n\n\t\t}\n\n\t\tdelay(1000);\n\n\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p>We shall randomize the data to be written to the W25QXX page zero every second.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Results:<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/im3.ezgif.com\/tmp\/ezgif-3-aa7c19c199.gif\" alt=\"\" \/><\/figure>\n\n\n\n<p>As you can see, we have successfully erased and wrote the new data to page0.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we saw how to read from a sector and get the required data. In this guide, we shall see how to erase a sector, write the new values. In this guide, we shall cover the following: Steps required to write to W25QXX. Enable\/Disable write. Sector erase. Write to a page. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-2160","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2160"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2160"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2160\/revisions"}],"predecessor-version":[{"id":2166,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2160\/revisions\/2166"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}