Hi
I have to access the OTP memory in winbond (W25Q128JW) NOR flash. Whenever i try access the program security register (42h), data is not written in the memory. I am using QUAD SPI protocol to communicate with flash. I use the nordic QSPI library. The General page write and read works fine whenever I try to access the OTP it will be no results.
Here I work with function
nrf_drv_qspi_cinstr_xfer to write and read commands. I attached the code for your reference.
1. How to access the security register in nrf52840?
2.Which function is to be used to get the output from the flash using qspi?
Thanks & Regards
Sriyogesh G
/** * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** @file * @defgroup qspi_example_main main.c * @{ * @ingroup qspi_example * * @brief QSPI Example Application main file. * * This file contains the source code for a sample application using QSPI. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "nrf_drv_qspi.h" #include "nrf_delay.h" #include "app_util_platform.h" #include "app_error.h" #include "boards.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include "sdk_config.h" #include "SEGGER_RTT.h" #include "SEGGER_RTT_Conf.h" #define QSPI_STD_CMD_WRSR 0x1 #define QSPI_STD_CMD_WRSR2 0x31 #define QSPI_STD_CMD_WRSR3 0x11 #define QSPI_STD_CMD_RSTEN 0x66 #define QSPI_STD_CMD_RST 0x99 #define WRITE_ENABLE 0x06 #define STATUS_REG1 0x05 #define READ_STATUS 0x35 #define READ_STATUS1 0x05 #define READ_STATUS3 0x15 #define SENDAA 0xAA #define SEND55 0x55 #define MANUFATURER_ID 0x94 #define FLASH_CMD_READ_SECURITY_REG 0x48 #define FLASH_CMD_PROGRAM_SECURITY_REG 0x42 #define FLASH_CMD_ERASE_SECURITY_REG 0x44 #define READ_JDEC 0x9F #define DEVICE_ADDRESS 0x002000 #define DEVICE_ADDRESS_READ 0x002000 void readStatusRegister(void); #define QSPI_TEST_DATA_SIZE 256 #define DATA_MINIMUM 20 #define WAIT_FOR_PERIPH() do { \ while (!m_finished) {} \ m_finished = false; \ } while (0) uint8_t initDeviceName[]={0x42,0x00,0x20,0x00,0X4E, 0X49, 0X56, 0X49}; uint8_t senddata[]={0x48,0x00,0x20,0x00,0xFF}; uint8_t deviceName[10]={0,0,0,0,0,0,0,0,0,0}; uint8_t sendBuffer[13]; uint32_t addree=0x002000; uint8_t dummybyte[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; static volatile bool m_finished = false; static void qspi_handler(nrf_drv_qspi_evt_t event, void * p_context) { UNUSED_PARAMETER(event); UNUSED_PARAMETER(p_context); m_finished = true; SEGGER_RTT_printf(0,"QSPI handler\r\n"); } void otpEnable(void) { uint32_t err_code; uint8_t send80=0x80; // uint8_t status1; uint8_t sent55=0x55; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode =SENDAA,//AAh .length = NRF_QSPI_CINSTR_LEN_2B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = false }; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, &sent55, NULL); APP_ERROR_CHECK(err_code); cinstr_cfg.opcode=QSPI_STD_CMD_WRSR;//01h cinstr_cfg.wren = true; nrf_gpio_pin_clear( NRF_GPIO_PIN_MAP(0,16)); err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, &send80, NULL); APP_ERROR_CHECK(err_code); nrf_gpio_pin_set( NRF_GPIO_PIN_MAP(0,16)); } void newwrite() { uint32_t err_code; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode =FLASH_CMD_PROGRAM_SECURITY_REG, .length = NRF_QSPI_CINSTR_LEN_1B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = true }; m_finished = false; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); APP_ERROR_CHECK(err_code); SEGGER_RTT_printf(0,"newwrite--%d",err_code); err_code = nrf_drv_qspi_write(&initDeviceName[0], 1, addree); SEGGER_RTT_printf(0,"newwrite--%d--%c\n",err_code,initDeviceName[0]); APP_ERROR_CHECK(err_code); } void newRead() { uint32_t err_code; uint8_t name=0; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode =FLASH_CMD_READ_SECURITY_REG, .length = NRF_QSPI_CINSTR_LEN_1B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = false }; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); SEGGER_RTT_printf(0,"newread--%d",err_code); APP_ERROR_CHECK(err_code); err_code = nrf_drv_qspi_read(&name, 1, addree); SEGGER_RTT_printf(0,"newread--%d--%X\n",err_code,name); APP_ERROR_CHECK(err_code); } void flashwrite(void) { ret_code_t err_code; m_finished = false; err_code = nrf_drv_qspi_write(&initDeviceName[0], 12, DEVICE_ADDRESS); APP_ERROR_CHECK(err_code); WAIT_FOR_PERIPH(); readStatusRegister(); SEGGER_RTT_printf(0,"device-%s-%d\n",initDeviceName,err_code); } void flashread(void) { ret_code_t err_code; m_finished = false; err_code = nrf_drv_qspi_read(&deviceName[0], 12, DEVICE_ADDRESS); APP_ERROR_CHECK(err_code); WAIT_FOR_PERIPH(); SEGGER_RTT_printf(0,"device-%s-%c\n",deviceName,deviceName[0]); for(int i=0;i<10;i++) { SEGGER_RTT_printf(0,"%c",deviceName[i]); } } void readStatusRegister(void) { uint8_t read=0,read1=0,read2=0; uint32_t err_code; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = READ_STATUS, .length = QSPI_CINSTRCONF_LENGTH_2B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = false }; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, &read); APP_ERROR_CHECK(err_code); cinstr_cfg.opcode=READ_STATUS1; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, &read1); APP_ERROR_CHECK(err_code); cinstr_cfg.opcode=READ_STATUS3; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, &read2); APP_ERROR_CHECK(err_code); // for(int i=0;i<3;i++) { SEGGER_RTT_printf(0,"StatusRead-%X-%x-%X\n",read2,read,read1); } } void writeEnableData(void) { uint32_t err_code; nrf_gpio_pin_clear( NRF_GPIO_PIN_MAP(0,16)); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = WRITE_ENABLE, .length = QSPI_CINSTRCONF_LENGTH_1B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = false }; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL,NULL); APP_ERROR_CHECK(err_code); nrf_gpio_pin_set( NRF_GPIO_PIN_MAP(0,16)); nrf_delay_ms(100); } void ProgramSecurityRegister() { uint32_t err_code; // m_finished = false; uint8_t storeAddress[6]; storeAddress[0]=0x00; storeAddress[1]=0x10; storeAddress[2]=0x01; storeAddress[4]=0x34; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = FLASH_CMD_PROGRAM_SECURITY_REG, .length = QSPI_CINSTRCONF_LENGTH_5B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = true }; nrf_gpio_pin_clear( NRF_GPIO_PIN_MAP(0,16)); err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg,&storeAddress[0], NULL); // nrf_delay_ms(100); APP_ERROR_CHECK(err_code); readStatusRegister(); nrf_gpio_pin_set( NRF_GPIO_PIN_MAP(0,16)); } void ReadSecurityRegister() { uint32_t err_code; // m_finished = false; uint8_t storeAddress[5]; storeAddress[0]=0x00; storeAddress[1]=0x10; storeAddress[2]=0x01; storeAddress[3]=0xFF; // // uint8_t rxdata[4]={0,0,0,0}; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = FLASH_CMD_READ_SECURITY_REG, .length = QSPI_CINSTRCONF_LENGTH_2B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = false }; nrf_gpio_pin_clear( NRF_GPIO_PIN_MAP(0,16)); // err_code= nrfx_qspi_lfm_start(&cinstr_cfg); err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg,&storeAddress[0],&deviceName[0]); APP_ERROR_CHECK(err_code); nrf_gpio_pin_set( NRF_GPIO_PIN_MAP(0,16)); for(int i=0;i<sizeof(deviceName);i++) { SEGGER_RTT_printf(0,"device-%x\n",deviceName[i]); } } void FlashOtpErase(void) { ret_code_t err_code; m_finished = false; uint8_t address[4]; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = FLASH_CMD_ERASE_SECURITY_REG, .length = NRF_QSPI_CINSTR_LEN_4B, .io2_level = true, .io3_level = true, .wipwait = true, .wren = true }; address[0]=0x00; address[1]=0x10; address[2]=0x01; nrf_gpio_pin_clear( NRF_GPIO_PIN_MAP(0,16)); err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, &address[0], NULL); SEGGER_RTT_printf(0,"errorcodeflasherase-%X",err_code); APP_ERROR_CHECK(err_code); nrf_gpio_pin_set( NRF_GPIO_PIN_MAP(0,16)); } void readJdec(void) { uint32_t err_code; uint8_t read[4]; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = READ_JDEC, .length = NRF_QSPI_CINSTR_LEN_4B, .io2_level = false, .io3_level = false, .wipwait = false, .wren = false }; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, &read[0]); SEGGER_RTT_printf(0,"errorcodeflasherase-%X\n",err_code); for(int i =0;i<4;i++) { SEGGER_RTT_printf(0,"jdec-%X",read[i]); } } void readuniqueid(void) { uint32_t err_code; uint8_t readone[8]; uint8_t sent[4]={0,0,0,0}; nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = READ_JDEC, .length = NRF_QSPI_CINSTR_LEN_8B, .io2_level = false, .io3_level = false, .wipwait = false, .wren = false }; err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, &sent[0], &readone[0]); SEGGER_RTT_printf(0,"errorcodeflasherase-%X\n",err_code); for(int i =0;i<8;i++) { SEGGER_RTT_printf(0,"ubique-%X",readone[i]); } } int main(void) { // uint32_t i; uint32_t err_code; err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_INFO("" "QSPI write and read example using 24bit addressing mode"); nrf_gpio_cfg_output(NRF_GPIO_PIN_MAP(0,16)); nrf_drv_qspi_config_t config = { .xip_offset = 0, .pins = { .sck_pin = NRF_GPIO_PIN_MAP(0,19), .csn_pin = NRF_GPIO_PIN_MAP(0,16), .io0_pin = NRF_GPIO_PIN_MAP(0,14), .io1_pin = NRF_GPIO_PIN_MAP(0,23), .io2_pin = NRF_GPIO_PIN_MAP(1,15), .io3_pin = NRF_GPIO_PIN_MAP(0,13), }, .prot_if = { .readoc = NRF_QSPI_READOC_READ4O, // 0x6B read command .writeoc = NRF_QSPI_WRITEOC_PP4O, // 0x32 write command .addrmode = NRF_QSPI_ADDRMODE_24BIT, .dpmconfig = false }, .phy_if = { .sck_delay = 100, .dpmen = false, .spi_mode = NRF_QSPI_MODE_0, .sck_freq = NRF_QSPI_FREQ_32MDIV4, // start with low 2 Mhz speed }, .irq_priority = 3 }; err_code = nrf_drv_qspi_init(&config, qspi_handler, NULL); APP_ERROR_CHECK(err_code); NRF_LOG_INFO("QSPI example started."); SEGGER_RTT_printf(0,"QSPI Started\r\n"); readJdec(); ProgramSecurityRegister(); ReadSecurityRegister(); readStatusRegister(); while(1) { } } /** @} */