2020-12-10 08:41 PM
I am using the Nucleo-L4r5zi with the octospi peripheral to communicate with a qspi NAND flash chip (W25N01GVZEIG). The octospi peripheral is set up in status polling mode to poll the state of the Write Enable bit in the flash status register. This is done after the Write Enable or Write Disable command is sent.
The problem I am having is instead of an expected ~120ns high pulse I always get a 10ns high pulse for the Write Enable bit in the flash status register. If I change the prescaler of the octospi register I still get a 10ns high pulse. If I send Write Disable instead of Write Enable command before polling the status register there is no high pulse (This is expected).
HCLK is running at 84mhz
Write Disable command (0x04):
Write Enable command (0x06):
Write Enable close up:
W25N01GV Datasheet:
Status Register (pg 20):
Status Register Read (pg 29):
Code:
Setup octospi:
//HCLK is 84mhz
//enable clocks
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOEEN;
//enable peripherals
RCC->AHB3ENR |= RCC_AHB3ENR_OSPI1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_OSPIMEN;
//I set up all the GPIO for the OCTOSPI peripheral right here (Not Shone)
OCTOSPI1->DCR1 |= (26 << OCTOSPI_DCR1_DEVSIZE_Pos);//128 M byte nand flash
OCTOSPI1->DCR2 |= ( 9 << OCTOSPI_DCR2_PRESCALER_Pos );//Octospi Prescaler to /10
OCTOSPI1->TCR |= OCTOSPI_TCR_SSHIFT;//Shift to prevent signal errors at high speed
Send write enable command:
OCTOSPI1->CR &= ~OCTOSPI_CR_FMODE;
OCTOSPI1->CCR &= ~( OCTOSPI_CCR_IMODE | OCTOSPI_CCR_DMODE | OCTOSPI_CCR_ADMODE );
OCTOSPI1->CCR |= (1 << OCTOSPI_CCR_IMODE_Pos);//Instruction on a single line
OCTOSPI1->CR |= OCTOSPI_CR_EN;//Enable the peripheral
OCTOSPI1->IR = 0x06;//load Write Enable command into the Instruction Register
while (OCTOSPI1->SR & OCTOSPI_SR_BUSY) {};//wait for octospi to finish
OCTOSPI1->CR &= ~OCTOSPI_CR_EN;//Disable the peripheral
Poll for write enable bit in flash status register:
OCTOSPI1->PSMKR = msk;//mask (NA right now)
OCTOSPI1->PSMAR = mat;//match (NA right now)
OCTOSPI1->PIR = 0x10;//polling interval
OCTOSPI1->CR |= (OCTOSPI_CR_APMS);//Set Automatic poll mode stop
OCTOSPI1->CR &= ~OCTOSPI_CR_FMODE;//clear Functional mode register
OCTOSPI1->CCR &= ~(OCTOSPI_CCR_IMODE | OCTOSPI_CCR_DMODE | OCTOSPI_CCR_ADMODE);
OCTOSPI1->CR |= (2 << OCTOSPI_CR_FMODE_Pos);//set Functional mode to Automatic-polling
OCTOSPI1->CCR |= (1 << OCTOSPI_CCR_IMODE_Pos);//set instruction mode to 1 (Instruction on a single line)
OCTOSPI1->CCR |= (1 << OCTOSPI_CCR_ADMODE_Pos);//set address mode to 1 (address on a single line)
OCTOSPI1->CCR |= (1 << OCTOSPI_CCR_DMODE_Pos);//set data mode to 1 (Data on a single line)
OCTOSPI1->CR |= OCTOSPI_CR_EN;//Enable the peripheral
OCTOSPI1->IR = 0x5;//set instruction to Read Status Register
OCTOSPI1->AR = 0xC0;//set address
while (OCTOSPI1->SR & OCTOSPI_SR_BUSY) {};//wait for octospi to finish
OCTOSPI1->CR &= ~OCTOSPI_CR_EN;//Disable the peripheral
I am just trying to get a pulse that lasts through the rising edge of the clock so that the stm32 can read the bit. Reading from the other status registers 0xA0, 0xB0 do not have any problems. The only problem I have is with the specific S1 (Write Enable Latch) bit in the 0xC0 status register. I have also tried other W25N01GVZEIG flash devices and have gotten the same result.
Thank you.
2020-12-11 03:37 PM
I don't know what is causing this but I have found that polling the status register before during and after a sector erase command gives different values for S1.
Before there is a 10ns pulse.
During, S1 is high the entire duration as it should be
After, S1 is low as it should be
I can read, program, and erase the chip even with this strange behavior. I think I am just not going to poll the state S1 because everything else works.