6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 11:28 am

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Sat Oct 03, 2020 8:15 am 
Offline

Joined: Tue Jun 19, 2018 8:28 am
Posts: 122
I am trying to add CF card support to some of my projects. Hardware had been already prepared for that (there is is CF card socket connected to the system bus) and I am able to initialize card. The is at least some communication between system and storage device. Now I need some functions to handle it correctly. My code is written in C and compiled with CC65. You can find its current version HERE

For now problematic problem is reading count of LBA sectors. I wrote following piece of code:

Code:
uint8_t cfGetSizeInfo(uint32_t *availableBlocks, uint16_t *sizeOfBlock) {
   uint16_t i=0;
   uint8_t tmp;
   
   *availableBlocks = 0x00000000;
   cfWait();
   CFREG7 = CMD_INFO_COMMAND;
   cfWait();
   while (CFREG7 & MASK_DRQ) {
      tmp = CFREG0;
      if (i == 120) { *availableBlocks |= (uint32_t)tmp; }
      else if (i == 121) {*availableBlocks |= ((uint32_t)tmp << 8); }
      else if (i == 122) {*availableBlocks |= ((uint32_t)tmp << 16); }
      else if (i == 123) {*availableBlocks |= ((uint32_t)tmp << 24); }
      i++;
      cfWait();
   }
   *sizeOfBlock = 512;
   return 1;
}


It was based on THIS example I found on-line, written in 6800 assembly. But it looks like there is something wrong, value displayed on the screen doesn't look right. Can you explain me what is the format of size info returned by 0xEC command? Is it a sequence of bytes constituting 32bit number? In that case what is its endianness? Or maybe it is a ASCII string? If so, in what format?

Also, is there some light FAT library which compiles into relative;y compact code with CC65? I tried FatFS but it nearly uses all of my EPROM space.


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 03, 2020 9:31 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
Well, I can't help you with C programming, but I've been working on a BIOS (65C02 assembly) for a Compact Flash adapter I put together recently. In any case, rather than find code online for doing this, I've referenced the SanDisk documentation attached here:

Attachment:
SanDisk CompactFlash Memory.pdf.zip [3.37 MiB]
Downloaded 88 times


Some questions regarding your hardware setup:
1- Are you running the CF Card in memory mode or True IDE mode?
2- Are you using a 16-bit data transfer or an 8-bit data transfer?
3- Are you using DMA or PIO transfers?
4- Are you using interrupts on the hardware?

My hardware adapter is using 16-bit data transfers and is setup for True IDE mode. For the ECh (Identify Device) command, you will need to setup the appropriate registers, send the command, then read the parameter data which is 512 bytes. The SanDisk documentation defines the layout of the 512-byte block of data that is returned when the Identify Device command is completed. The LBA block count is part of this parameter block. Section 5.1.5 details this. Words 60-61 (4 bytes) contains the LBA count of the device.

Note: for 16-bit transfers, the upper byte (D8-D15) needs to be stored in memory followed by the lower byte (D0-D7). You can check this by examining the memory address used for the buffer. The first two bytes should be 848Ah.

You can look at this link for some PIO mode code to read and write blocks in LBA mode and take a look at a 512-byte buffer from an identify command:
viewtopic.php?f=4&t=6223#p78135

Hope this helps.... for me at least, getting the basic hardware functions working is pretty straightforward in assembly language and can be quite small as well.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 03, 2020 10:17 am 
Offline

Joined: Tue Jun 19, 2018 8:28 am
Posts: 122
floobydust wrote:
Some questions regarding your hardware setup:
1- Are you running the CF Card in memory mode or True IDE mode?
2- Are you using a 16-bit data transfer or an 8-bit data transfer?
3- Are you using DMA or PIO transfers?
4- Are you using interrupts on the hardware?


I am using 8bit data transfer. No interrupts nor DMA.
Configuration is the sam as in 6800 example I've mentioned above:

Code:
********************************
* INITIALIZE CF
********************************
CFINIT   LDAA   #$04      RESET COMMAND
   STAA   CFREG7
   JSR   CFWAIT
   LDAA   #$E0      LBA3=0, MASTER, MODE=LBA
   STAA   CFREG6
   LDAA   #$01      8-BIT TRANSFERS
   STAA   CFREG1
   LDAA   #$EF      SET FEATURE COMMAND
   STAA   CFREG7
   JSR   CFWAIT
   JSR   CFCHERR
   RTS


Which in my case is:

Code:
uint8_t cfInit(void) {
   CFREG7 = CMD_RST;
   cfWait();
   CFREG6 = 0xE0;            // LBA3=0, MASTER, MODE=LBA
   CFREG1 = 0x01;            // 8-BIT TRANSFERS
   CFREG7 = 0xEF;            // SET FEATURE COMMAND
   cfWait();
   // check for error now and return
   if (CFREG7 & MASK_ERROR) return 1;
   return 0;
}


Quote:
Words 60-61 (4 bytes) contains the LBA count of the device.


So, in case (8bit transfer mode) this information will be stored in bytes 120-123.
I do not store entre data sequence in 512 bytes long buffer. I simply count incoming bytes and operate or those, which I am interested in.
So, is my current version of the code valid?

Code:
uint8_t cfGetSizeInfo(uint32_t *availableBlocks, uint16_t *sizeOfBlock) {
   uint16_t i=0;
   uint8_t tmp;
   
   *availableBlocks = 0x00000000;
   cfWait();
   CFREG7 = CMD_INFO_COMMAND;
   cfWait();
   while (CFREG7 & MASK_DRQ) {
      tmp = CFREG0;
      if (i == 120) { *availableBlocks |= (uint32_t)tmp; }
      else if (i == 121) {*availableBlocks |= ((uint32_t)tmp << 8); }
      else if (i == 122) {*availableBlocks |= ((uint32_t)tmp << 16); }
      else if (i == 123) {*availableBlocks |= ((uint32_t)tmp << 24); }
      i++;
      cfWait();
   }
   *sizeOfBlock = 512;
   return 1;
}


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 03, 2020 10:58 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
I'm not a C programmer, so I can't really help you on that one..... I would suggest that you read the full 512 bytes from the CF Card to complete the operation.

If you look at the linked code and the 512 byte buffer, locations $0478 - $047B show as:

$7A $80 $00 $00

The first two bytes are the low-order word, the second two bytes are the high order word and are in big endian format, so the block count in hex is $7A80, which 31360 in decimal. This is correct for my 16MB SanDisk card.

Posting a schematic of your CF-Card hardware might be valuable.... to see if there's any possible problems there.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 03, 2020 5:44 pm 
Offline

Joined: Tue Jun 19, 2018 8:28 am
Posts: 122
Ok, I was able to make it work. It turned out that function reading the number ob sectors was fine. Different part of my code was causing problems - wrong variable type in function displaying it.
Now I have even more important question. Is there some lightweight file system written in C or 6502 assembly, that I could use in my system?
I tried to use FatFS. It even compiled after some workarounds, however:
1) it requires a large amount of EPROM memory - 32kB chip is nearly ful now and I need some space for additional feature I a going to add in the future.
2) For some reason it doesn't work anyway. Device resets itself if I try to use it with FatFS active.

Is there some alternative? I know about PetitFS, but it has some serious limitations when it comes to appending new data to existing file.
To be honest, I do not even need FAT support. It just as well can be some obscure FS, as long I'll be able to access the card content under Linux.
I do not need directories. Writing to main directory of the card will be just fine.


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 03, 2020 6:42 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
Atlantis wrote:
Ok, I was able to make it work. It turned out that function reading the number ob sectors was fine. Different part of my code was causing problems - wrong variable type in function displaying it.
Now I have even more important question. Is there some lightweight file system written in C or 6502 assembly, that I could use in my system?
I tried to use FatFS. It even compiled after some workarounds, however:
1) it requires a large amount of EPROM memory - 32kB chip is nearly ful now and I need some space for additional feature I a going to add in the future.
2) For some reason it doesn't work anyway. Device resets itself if I try to use it with FatFS active.

Is there some alternative? I know about PetitFS, but it has some serious limitations when it comes to appending new data to existing file.
To be honest, I do not even need FAT support. It just as well can be some obscure FS, as long I'll be able to access the card content under Linux.
I do not need directories. Writing to main directory of the card will be just fine.


Maybe look at Apple DOS 3.3. One directory, long filenames, etc. Read the book (online, PDF) Beneath Apple DOS for the internal details.

I implemented a variant of ProDOS on my Ruby system (in C, runs on the ATmega that controls the SD card).

You may also want to look at the various Acorn DFS formats - all well documented on e.g. stardot.org.uk and other places.

The down-side of these is reading/writing them from Linux.... I have a plan to write a FUSE driver for mine, but meanwhile I have an "FTP" type program that gets/sends files via the serial line, or I can 'dd' the entire SD card (or partition at a time) for backup/archive purposes.

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 03, 2020 7:34 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
Glad you were able to get your C code working. In addition to what Gordon posted, there's a couple other filesystems being ported over to the 6502.

1- BillG (on this forum) has been porting Flex (initially for the 6800) to the 6502 and there's a long post here:
viewtopic.php?f=2&t=6085

2. Richard Leary wrote DOS/65 some years ago, which is basically a port of CP/M. He's been working on V3 and does have some early code working:
viewtopic.php?f=1&t=4634&hilit=leary#p55032

Either of these should be able to support the CF Card once you write a compatible BIOS and/or translation layer to what the OS/filesystem requires... both for the CF Card and a console. For my system, I'm looking to try and get both of these running. I currently use Xmodem-CRC to download and upload files via the console serial port, which has been working fine. I'm certain a simple utility can be written to create an image file to a host PC for backup and cloning if needed.

While I think it would be nice have the ability to access the CF Card from a Linux system, that might require a pretty large amount of code to implement a supported filesystem on the 65(C)02, or take Gordon's approach. Some time ago, I was looking at the Minix filesystem... but even this looks to be more involved than implementing the Flex or CP/M file structures. Then again, it's always possible someone can or will find a way to do it.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 49 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: