According to TRM, software needs to check interrupt status bits(Tx/Rx/command FIFO empty) to determine whether the transfer is complete; is it possible that despite all these bits are set, but the transmit data still in the shift register?
We found when the bus clock is low(~10MHz), extra delay needs to be added after all FIFO empty bits are set, before deactivating CS, otherwise data (less than 4 bytes) at the end of data block might not be transmitted to the flash.
@wzheng , 4 bytes are left because the interrupt for the TX FIFO is asserted according to the value in the TX_thres register. By default it's 1, meaning the interrupt is asserted when 1 word (4 bytes) is left in the FIFO. Change the register value.