Closed dvoytik closed 7 years ago
CC @Sangjin-Lee
You should call the function V2FIsControllerBusy and make sure that the channel controller is not busy before an operation. e.g.) while (V2FIsControllerBusy(chCtlReg[0])) { / spin / } V2FEraseBlockAsync(...); while (V2FIsControllerBusy(chCtlReg[0])) { / spin / } V2FStatusCheckAsync(...);
Hi @Cosmos-OpenSSD, thank you for your response. I've changed the test code according to your suggestions:
#include "low_level_scheduler.h"
#include "fmc_driver.h"
#include "memory_map.h"
#include "init_ftl.h"
#include <stdio.h>
void test_read()
{
unsigned int chNo;
unsigned int wayNo;
unsigned int *status = (unsigned int *)(COMPLETE_TABLE_ADDR);
void *pageDataBuf = (void *)BUFFER_ADDR;
void *spareDataBuf = (void *)SPARE_ADDR;
unsigned int *errorInfo = (unsigned int *)ERROR_INFO_TABLE_ADDR;
printf("test read start Nov 8, 10:41...\r\n");
InitChCtlReg();
for(chNo = 0; chNo < CHANNEL_NUM; ++chNo) {
for(wayNo = 0; wayNo < WAY_NUM; ++wayNo) {
V2FResetSync(chCtlReg[chNo], wayNo);
V2FEnterToggleMode(chCtlReg[chNo], wayNo);
}
}
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
//#if 0 // UNCOMMENT THIS LINE to disable erase operation
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FEraseBlockAsync(chCtlReg[0], 0, 0);
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
while (1) {
while (!(*status & 1)) { /* spin */ }
if (((*status >> 1) & 0x60) == 0x60) {
if ((*status >> 1) & 3) {
printf("FAIL: status: %x", *status);
}
break;
// again
}
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
}
//#endif // UNCOMMENT THIS LINE to disable erase operation
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FReadPageTransferAsync(chCtlReg[0], 0, pageDataBuf, spareDataBuf,
errorInfo, status, 1);
// HERE: this loop never ends, *status value is always 0x0
while (!(*status & 1)) { /* spin */ }
printf("test read OK\r\nReboot me please.\r\n");
for (;;) {}
}
Unfortunately the result is the same - after executing V2FReadPageTransferAsync() command the *status is never updated. I marked the line where it hangs with the comment "HERE".
Please note, that I don't test the latest commit (i.e. v1.0.2). I use commit 3242242 2017-08-23 openssd J89 (on) -> J82 (off) @ p.63
(i.e. v1.0.0) because of the issue #10.
In addition, you need to call V2FReadPageTriggerAsync before V2FReadPageTransferAsync. Reading a page should be like:
@Cosmos-OpenSSD, thank you for the quick response. I could manage to make V2ReadPageTransferAsync to work. I'd add to your list one important detail - we have to send StatusCheck in loop while it response with AGAIN status.
Now I have another problem. I get error - CRC is invalid. My code:
#include "low_level_scheduler.h"
#include "fmc_driver.h"
#include "memory_map.h"
#include "init_ftl.h"
#include <stdio.h>
void erase(unsigned int row_addr)
{
unsigned int *status = (unsigned int *)(COMPLETE_TABLE_ADDR);
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FEraseBlockAsync(chCtlReg[0], 0, row_addr);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
while (1) {
while (!(*status & 1)) { /* spin */ }
if (((*status >> 1) & 0x60) == 0x60) {
if ((*status >> 1) & 3) {
printf("FAIL: status: %x", *status);
}
break;
}
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
}
}
void test_read()
{
unsigned int chNo;
unsigned int wayNo;
unsigned int *status = (unsigned int *)(COMPLETE_TABLE_ADDR);
void *pageDataBuf = (void *)BUFFER_ADDR;
void *spareDataBuf = (void *)SPARE_ADDR;
unsigned int *errorInfo = (unsigned int *)ERROR_INFO_TABLE_ADDR;
printf("test read (Nov 9, 11:24)...\r\n");
InitChCtlReg();
for(chNo = 0; chNo < CHANNEL_NUM; ++chNo) {
for(wayNo = 0; wayNo < WAY_NUM; ++wayNo) {
V2FResetSync(chCtlReg[chNo], wayNo);
V2FEnterToggleMode(chCtlReg[chNo], wayNo);
}
}
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
erase(0);
erase(1);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FReadPageTriggerAsync(chCtlReg[0], 0, 1);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
while (1) {
while (!(*status & 1)) { /* spin */ }
if (((*status >> 1) & 0x60) == 0x60) {
if ((*status >> 1) & 3) {
printf("FAIL: status: %x", *status);
}
break;
}
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
}
memset(errorInfo, 0x0, 4 * 12);
V2FReadPageTransferAsync(chCtlReg[0], 0, pageDataBuf, spareDataBuf,
errorInfo, status, 0);
while (!(*status & 1)) { /* spin */ }
if(!V2FCrcValid(errorInfo[0])) { // THIS ERROR
printf("CRC invalid\r\n");
}
if(V2FSpareChunkValid(errorInfo[0])) {
printf("spare chunk invalid\r\n");
}
if(V2FPageChunkValid(errorInfo[1])) {
printf("page chunk invalid\r\n");
}
if(V2FWorstChunkErrorCount(errorInfo[0])> BIT_ERROR_THRESHOLD) {
printf("ErrofInfo BIT_ERROR_THRESHOLD\r\n");
}
printf("test read OK\r\nReboot me please.\r\n");
for (;;) {}
}
Could it be related to the issue #10?
You erased the block 0 twice (row address 0 and 1 are in a same block) and read the page 1 without any program operation. This might lead to ECC/CRC errors because the page was erased and does not have meaningful data and ECC/CRC information.
The read buffer should be filled with 0xFFs at the error point.
@Cosmos-OpenSSD, with only erase and without program after read the buffer is filled some random garbage.
Sorry, I forgot to say that V2FReadPageTransferRawAsync should do that. V2FReadPageTransferAsync includes a descrambling process, so garbage data will be returned.
@Cosmos-OpenSSD, and if I program some data before read then it should work? This code I've just tried:
#include "low_level_scheduler.h"
#include "fmc_driver.h"
#include "memory_map.h"
#include "init_ftl.h"
#include <stdio.h>
void erase(unsigned int row_addr)
{
unsigned int *status = (unsigned int *)(COMPLETE_TABLE_ADDR);
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FEraseBlockAsync(chCtlReg[0], 0, row_addr);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
while (1) {
while (!(*status & 1)) { /* spin */ }
if (((*status >> 1) & 0x60) == 0x60) {
if ((*status >> 1) & 3) {
printf("FAIL: status: %x", *status);
}
break;
}
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
}
}
void program_page_with_zeros(unsigned int row_addr)
{
unsigned int *status = (unsigned int *)(COMPLETE_TABLE_ADDR);
void *pageDataBuf = (void *)BUFFER_ADDR;
void *spareDataBuf = (void *)SPARE_ADDR;
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
// zero memory buffers
memset(pageDataBuf, 0x0, 16 * 1024);
memset(spareDataBuf, 0x0, 256);
V2FProgramPageAsync(chCtlReg[0], 0, row_addr, pageDataBuf, spareDataBuf);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
while (1) {
while (!(*status & 1)) { /* spin */ }
if (((*status >> 1) & 0x60) == 0x60) {
if ((*status >> 1) & 3) {
printf("FAIL: status: %x", *status);
}
break;
}
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
}
}
void test_read()
{
unsigned int chNo;
unsigned int wayNo;
unsigned int *status = (unsigned int *)(COMPLETE_TABLE_ADDR);
void *pageDataBuf = (void *)BUFFER_ADDR;
void *spareDataBuf = (void *)SPARE_ADDR;
unsigned int *errorInfo = (unsigned int *)ERROR_INFO_TABLE_ADDR;
printf("test read (Nov 9, 12:42)...\r\n");
InitChCtlReg();
for(chNo = 0; chNo < CHANNEL_NUM; ++chNo) {
for(wayNo = 0; wayNo < WAY_NUM; ++wayNo) {
V2FResetSync(chCtlReg[chNo], wayNo);
V2FEnterToggleMode(chCtlReg[chNo], wayNo);
}
}
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
erase(0);
erase(1);
program_page_with_zeros(0);
program_page_with_zeros(1);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FReadPageTriggerAsync(chCtlReg[0], 0, 1);
while (!(V2FReadyBusyAsync(chCtlReg[0]) & 1)) { /* spin */ }
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
while (1) {
while (!(*status & 1)) { /* spin */ }
if (((*status >> 1) & 0x60) == 0x60) {
if ((*status >> 1) & 3) {
printf("FAIL: status: %x", *status);
}
break;
}
while (V2FIsControllerBusy(chCtlReg[0])) { /* spin */ }
V2FStatusCheckAsync(chCtlReg[0], 0, status);
}
memset(errorInfo, 0x0, 4 * 12);
memset(pageDataBuf, 0x55, 16 * 1024);
V2FReadPageTransferAsync(chCtlReg[0], 0, pageDataBuf, spareDataBuf,
errorInfo, status, 0);
while (!(*status & 1)) { /* spin */ }
dumpmem(pageDataBuf, 16);
if(!V2FCrcValid(errorInfo[0])) { // THIS ERROR
printf("CRC invalid\r\n");
}
if(V2FSpareChunkValid(errorInfo[0])) {
printf("spare chunk invalid\r\n");
}
if(V2FPageChunkValid(errorInfo[1])) {
printf("page chunk invalid\r\n");
}
if(V2FWorstChunkErrorCount(errorInfo[0])> BIT_ERROR_THRESHOLD) {
printf("ErrofInfo BIT_ERROR_THRESHOLD\r\n");
}
printf("test read OK\r\nReboot me please.\r\n");
for (;;) {}
}
Still I get "CRC invalid" and garbage data:
0x10000000 08 08 08 08 10 10 10 10 21 21 21 21 42 42 42 42 |........!!!!BBBB|
It seems that you were trying to read page 1 (V2FReadPageTrigger(..., 1), but V2FReadPageTransferAsync(..., 0) was trying to read page 0. The descrambling process uses a row address for a seed, so you should give correct row address to V2FReadPageTransferAsync.
@Cosmos-OpenSSD, oops! You are right. I changed this and now finally it works! :) Thank you for the help!
Reading operation doesn't work if an erase and/or a program operation was issued before:
If you remove lines marked as "REMOVE THIS LINE" in the above code example then the erase command is executed before the read page command. *status variable is never updated and the last while loop always spins.
Could you please check if you also can observe this issue? I test this code on commit
3242242 2017-08-23 openssd J89 (on) -> J82 (off) @ p.63
because the latest commit doesn't work (please see #10)