OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 2:08 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 44 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:25 am 
Offline
Member
Member

Joined: Wed Aug 29, 2018 4:42 pm
Posts: 122
umm if you say the 'outw' function i've just deleted it, i didn't even knew that it was there


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:26 am 
Offline
Member
Member
User avatar

Joined: Mon Sep 03, 2018 2:25 am
Posts: 66
include/system/system.h
include/system/system.c

Also .c files should go in their own directory and not in the include folder


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:27 am 
Offline
Member
Member

Joined: Wed Aug 29, 2018 4:42 pm
Posts: 122
ok, i deleted it from github and from my code, now there should only be a 'inportb' and 'outportb' function


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:34 am 
Offline
Member
Member

Joined: Wed Aug 29, 2018 4:42 pm
Posts: 122
if i do
Code:
outportb(ADDRESS_REG, param)
instead of get first the param and then the ADDRESS_REG it even doesnt print when i try to convert it to decimal


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:38 am 
Offline
Member
Member
User avatar

Joined: Mon Sep 03, 2018 2:25 am
Posts: 66
You're also trying to feed an integer into the print char function you need an int to ascii(itoa) function. Strings are encoded in the ASCII format but integers are not.


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:42 am 
Offline
Member
Member

Joined: Wed Aug 29, 2018 4:42 pm
Posts: 122
so i should convert it to ascii values instead of an integer?


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 8:47 am 
Offline
Member
Member
User avatar

Joined: Mon Sep 03, 2018 2:25 am
Posts: 66
You should use an itoa function to fill in a buf with that number represented in ASCII to give to printf


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 9:48 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
thomtl wrote:
include/system/system.h
include/system/system.c

Also .c files should go in their own directory and not in the include folder

I wasn't going to say this, because while this does go against convention, it really is just convention. Still, I agree that it would make sense to change it to fit that convention, both as a means of managing the files, and to avoid confusion.

I also was wondering why you included the binaries (the .o files and such) in the Git repo; usually, this would be excluded (using the .gitignore file to set which files not to add) because a) you usually only want to have the source files and documentation in the repo (and maybe some of the resource files such as images/tilesets/etc, though these would usually be in a separate repo if there a large number of them), to reduce disk and bandwidth usage, b) the object files corresponding to any touched source files (those which have edited since the most recent make) will be regenerated whenever the code is compiled, and c) distributing executable (or just linkable) binaries without a hash signature presents trust issues, even if you have no malicious intent.

I've tested the bcdtoint() function, and found that it does work correctly; however, for the sake of clarity (and some improvement in speed, at the potential cost of runtime stack use depending on compiler optimization), I am re-writing it with a bit more explanation, along with a corresponding Int to Packed BCD function. I'll post those in a little while, once I have finished testing my version of it.

EDIT: Here's the test code I mentioned. As I said, it doesn't look as if the BCD-to-integer conversion was to issue anyway, but I figured I would include it for the sake of completeness. Also, I deliberately spread the conversions out a bit to make them easier to read.

Code:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

uint8_t nybbles_to_bcd(uint8_t hi, uint8_t lo)
{
   if (hi > 9 || lo > 9)
      return 0xff;   // give an out-of-bounds error code

   // move the value of 'hi' to upper nybble then OR with 'lo'
   return ((hi << 4) | lo);
}

uint8_t uint_to_bcd(uint8_t value)
{
   uint8_t hi, lo;

   if (value > 99)
   {
      return 0xff;  // give an out-of-bounds error code
   };

   lo = value % 10;    // the hex value of the unit decimal
   hi = (value / 10);  // the decimal value of the tens decimal
   hi *= 16;           // convert the tens decimal to hex 

   assert((hi >> 4) < 10);
   assert(lo < 10);
   return hi | lo;
}

// ucbd_to_unint - converts 1-byte unpacked BCD value to
// a 1-byte binary integer
uint8_t bcd_to_uint(uint8_t bcd)
{
   uint8_t hi, lo;
   hi = bcd >> 4;      // shift high nybble into low nybble
   lo = bcd & 0x0f;    // mask off upper nybble

   hi *= 10;

   // alt. version to tweak performance - the compiler's optimizer
   // should be smart enough to emit this code for you
   // automatically anyway, but it might be worth knowing
   // hi = (hi << 3) + hi + hi;

   assert((hi + lo) < 100);
   return  hi + lo;
}

int main(void)
{
   uint8_t a, a_prime, b, c, d, e;

   do
   {
      puts("Enter a two one-digit decimal values to convert: ");
      scanf("%hhu %hhu", &a, &a_prime);
      b = nybbles_to_bcd(a, a_prime);
      if (b == 0xff)
      {
         printf("either %hhu or %hhu has more than two digits, please try again\n", a, a_prime);
         a = 1;
         continue;
      }

      printf("%hhu%hhu as Packed BCD ", a, a_prime);   
      printf("- hex %hhx, decimal %hhu\n", b, b);
      c = bcd_to_uint(b);
      printf("bcd_to_uint() returns: hex %hhx, decimal %hhu\n", c, c);
      puts("converting back to BCD -");
      d = uint_to_bcd(c);
      if (d == 0xff)
      {
         printf("%hhu is more than two digits, please try again\n", c);
         a = 1;
         continue;
      }

      printf("hex %hhx, decimal %hhu\n", d, d);
      e = bcd_to_uint(d);
      printf("bcd_to_uint() returns: hex %hhx, decimal %hhu\n", e, e);
   }
   while ((a + a_prime) != 0);

   return 0;
}

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Mon Oct 15, 2018 6:49 pm 
Offline
Member
Member

Joined: Wed Aug 29, 2018 4:42 pm
Posts: 122
thanks for the code! in the repo are the .bin and .o files 'cause i want to have an apart dir to have the .o and bin files, and if you see a 'obin' directory you probably won't know what's the reason of it, so you can enter and see whats in

EDIT:
when i compile the code, ld gives: undefined reference to '__assert_fail'
it's a problem from the assert function, but the assert.h is included


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Tue Oct 16, 2018 10:08 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
alberinfo wrote:
in the repo are the .bin and .o files 'cause i want to have an apart dir to have the .o and bin files, and if you see a 'obin' directory you probably won't know what's the reason of it, so you can enter and see whats in


Oh, I get that, I think, but my point is that while you might want a directory for them on the individual development hosts, you usually wouldn't want the Object Files themselves in the online hosted repo - they just take up space on the cloud host, and increase the download bandwidth for anyone else who is cloning or forking the repo.

Git itself has a way of handling this, with a hidden resource file called '.gitignore'. This lets you update the Git repo while omitting certain files or file types that are in the repo's directory structure, but which don't need to be bundled into the repo package itself (because they are redundant, are automatically generated by the build system, only apply to the local system, or anything else like that).

The official documentation for this is on the Git website. You might want to read this James Coyle tutorial which explains this in greater depth. Note that this is a function of Git, not of the GitHub host, so it would work for any other host using Git; other Source Control tools such as Subversion or Mercurial have their own ways of getting the same results.

I don't know how well you know Git and GitHub, so you might want to look at this tutorial if you don't know it all that well yet, as well as more of the Atlassian Git tutorial I've already linked to.

The practical upshot of this is that if you add a .gitignore file to the top directory of your Slidoor-OS repo, with the following directives, it should omit the object files, libraries (the *.a files, which are basically just a collection of several *.o files bundled together, the *.so are similar, but are used for share libraries, something your OS presumably doesn't support yet) as well as things like backup files and other non-essentials:

Code:
# build-generated binaries
*.o
*.elf
*.a
*.so
*.d
*.bin
/bin
*.iso

# linker-generated data files
*.map

# various types of backup files
*.*~
%*%
*.bak

# log files and directories
/log
*.log


This will leave these files in your local host's file structure, but omit them from the uploaded files whenever you push to the cloud host. A more extensive 'default' .gitignore for C development in general can be found here, though you need to keep in mind that this is only an example file - you can, and probably should, modify it to suit your own needs.

I don't know if you have a specific need to include the /obin directory itself, or its contents, or the .iso file for the disk image, but if you don't, you can do this so that they don't take up space on the cloud-hosted repo.

alberinfo wrote:
when i compile the code, ld gives: undefined reference to '__assert_fail'
it's a problem from the assert function, but the assert.h is included


On the one hand, I was using that to test the code; you should be able to remove the asserts without any problems.

OTOH, it would make sense to address the problem itself, which is that you don't have a library with the assert function in it. See the wiki page Creating a C Library for details about how to fix this.

Which brings up another issue with your header files: some of the functions are in the header files, including the bcdtoint() function. this is an extremely poor idea. The wiki has a page which explains the reasons for this in depth, but the important thing here is that (with the exceptions of inlined functions, macros, and in C++, templates) functions should be in a separate source file, which can be compiled to linkable object files, with only the function prototype in the header.

The Object Files are, of course, the compiled results of the individual compiled source; these are what the linker works on to build the final executable binary, and the object files are usually in a variant of the Executable Format used for that executable. But this is all 'you should know this already' stuff, so I don't want to insult your intelligence by belaboring it.

I will mention that you generally don't want to #include headers inside of other headers, and you should put header guards around the body of the header to prevent repeated inclusions (which can cause 'multiple definition' errors).

On a slightly related note: don't name the entry point to your kernel main(). the main() function has a very specific use in C, with a specific set of allowable function signatures, and using the name main() for anything else tends to break a lot of things. You probably want to use a name such as kmain() or something. I'm frankly surprised it compiled at all as it is - if you were using the recommended warnings, such -Wall and -Wextra, in your command line options (something I strongly recommend for any GCC builds), it would have flagged this.

I also recommend that instead of a hand-coded shell script, you use a build automation tool such as GNU Make, CMake, Ant, Ninja, Meson, or the like. Some are based on the classic Unix make(1) tool, while others might use XML files or some forms of GUI tooling; the point is that they do a lot of this work for you, which ever one you choose, and don't depend on their being a BASH shell to run the script in (meaning they are more usable under, say, Windows).

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Tue Oct 16, 2018 2:10 pm 
Offline
Member
Member

Joined: Wed Aug 29, 2018 4:42 pm
Posts: 122
ok.. i'm already thinking that there's something wrong with the get_RTC_val() function and not with the conversion from bcd to int, now i got the image posted below(also i've updated the github repo, so you'll can see the code)


Attachments:
cmos bug2.jpg
cmos bug2.jpg [ 11.08 KiB | Viewed 1536 times ]
Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Tue Oct 16, 2018 5:25 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 692
I'm going to make a serious recommendation. If you intend to use QEMU you should consider using remote symbolic debugging. When assembling with NASM use -g -F dwarf and with GCC use -g to enable debug information. Then spin up QEMU and GDB with something like:
Code:
qemu-system-i386 -rtc base=2011-11-11T11:11:00 -cdrom Slidoor.iso -S -s &
gdb obin/bootloader.bin \
        -ex 'target remote localhost:1234' \
        -ex 'break *main' \
        -ex 'layout src' \
        -ex 'continue'


The -rtc base is convenient if you are trying to set the day and time to a known value. I'm also using qemu-system-i386 rather than the 64-bit version to keep GDB and QEMU in sync with the type of code that is running.


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Tue Oct 16, 2018 5:27 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 692
Schol-R-LEA wrote:
On a slightly related note: don't name the entry point to your kernel main(). the main() function has a very specific use in C, with a specific set of allowable function signatures, and using the name main() for anything else tends to break a lot of things. You probably want to use a name such as kmain() or something. I'm frankly surprised it compiled at all as it is - if you were using the recommended


I don't believe the standard puts any restrictions on main's prototype when compiling for a non-hosted environment using GCC's -ffreestanding option


Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Tue Oct 16, 2018 6:39 pm 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
OK, before I look at the problem, I think I may have misstated some of the stuff about the headers; you only needed to move the functions out of the header. The declarations for things like macros, typedefs, and shared constants should be in a header, as should be the function prototypes.

(Shared variables are a bit more complicated - those should have a declaration in the header file, and a definition in the source file, which looks like so:

Code:
extern int foo;   // in the header file

int foo;     // in the source file


And yes, that's almost, but not quite, the same, a fact which makes it easy to get turned around. The difference is that the declaration only says what the variable is, while the definition - like a function definition - allocates memory for the variable and does similar preparation for it.)

Also, note that the types defined in stdint.h are all postfixed with '_'t', just like the size_t type is. I know that you have your own 'types.h' header, but I would recommend replacing that with appropriate versions of the standard type headers (stdint.h, stdbool.h, stdfloat.h. etc.) for your compiler and OS. The OpenGroup website (which handles the POSIX standard for Unix-like systems) has documentation for all of the POSIX standard versions of the headers (which more or less match those for the C11 standard, though they also include several Unix-specific ones), so you may want to review those before implementing or porting any C headers and libraries.

So, for example, the assert.h file usually contains just a single macro definition, a simple if not especially complete version of which might be:
Code:
/* assert.h - utility macro for basic sanity-check testing

/* to use this as an example, you set up the header guards like so -
these will ensure that the header body only gets compiled
once per compilation unit */
#ifndef __ASSERT_H__
#define __ASSERT_H__

/* this is just a stub version, which assumes that there is some
abort or exit operation that it can call. A more complete version
would do things like print the failed assertion. You would have to use
whatever you implement in your OS to do this. */

#define assert(exp) if (!(exp)) exit(-1); // assumes 'exit()' exists

#endif   // close assert .h body


Stepping up a bit in complexity, a bcd.h header and library might be:
Code:
/* bcd.h - declarations for packed-BCD-related functions */
#ifndef __BCD__H__
#define __BCD__H__

typedef uint8_t bcd_t;

/* constants for the BCD functions
MAX_BCD and MIN_BCD are the largest and smallest values
representable by a one-byte packed BCD value. MAX_BCD_INPUT.
The binary representation of a packed BCD is such that the two nibbles
have the equivalent *hex* values of the digits, not the decimal values,
and the value ranges are disjoint - there are 8-bit binary values which do
not represent a BCD value at all.

MAX_BCD_INPUT is that largest binary value that can be converted to
a Packed Binary-Coded Decimal value.

ERR_BCD_OVF is an out-of-range error code for indicating that
the value being converted exceeded MAX_BCD_INPUT.
*/
#define MAX_BCD 0x99
#define MIN_BCD 0
#define MAX_BCD_INPUT 99
#define ERR_BCD_OVF 0xFF   

bcd_t uint_to_bcd(uint8_t value);
uint8_t bcd_to_int(bcd_t bcd);

#endif   // closing body of bcd.h


I've omitted the 'nybbles_to_bcd()' function, as that was simply part of my testing scaffolding, not something you are likely to ever need.

bcd.c
Code:
/* bcd.c - functions for handling BCD values */

// make sure that stdint.h is included before bcd.h
#include <stdint.h>
#include "bcd.h"

bcd_t  uint_to_bcd(uint8_t  value)
{
    uint8_t  hi, lo;
    if(value > MAX_BCD_INPUT)
    {
        return ERR_BCD_OVF ;
    };
    lo = value % 10;
    hi = (value / 10);
    hi *= 16;
    return hi | lo;
}

uint8_t  bcd_to_int(bcd_t  bcd)
{
    uint8_t  hi, lo;
    hi = bcd >> 4;
    lo = bcd & 0x0F;
    hi *= 10;
    return hi + lo;
}


And yes, I am suggesting keeping these separate; while BCD doesn't come up often, it occurs often enough that a simple stand-alone library like this might be worth having on hand. Given this, this would give you a cmos.h like this:

Code:
/* cmos.h - declarations related to the CMOS settings
and Real-Time Clock */
#infdef __CMOS_H__
#define __CMOS_H__

#define ADDRESS_REG     0x70
#define DATA_REG        0x71

/* Values/Commands for RTC Registers */
#define SECOND          0x00    //Second      00-59
#define MINUTE          0x02    //Minute      00-59
#define HOUR            0x04    //Hour        00-23
#define DAY_OF_WEEK     0x06    //Day of Week 01-0DAY
#define DAY             0x07    //Day         00-31
#define MONTH           0x08    //Month       00-12
#define YEAR            0x09    //Year        00-99

/* function declarations */
uint8 get_RTC_val(uint8 param);
bool isupdateinprogress();
void set_RTC_val(uint8 param, uint8 setVal);
int get_rtc(void);

#endif


I'll address the functions shortly; suffice it to say, I am pretty sure that the function signatures are going to change, so those prototypes will have to, too.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Last edited by Schol-R-LEA on Tue Oct 16, 2018 6:55 pm, edited 4 times in total.

Top
 Profile  
 
 Post subject: Re: print correctly BCD CMOS RTC values
PostPosted: Tue Oct 16, 2018 6:42 pm 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
MichaelPetch wrote:
Schol-R-LEA wrote:
On a slightly related note: don't name the entry point to your kernel main(). the main() function has a very specific use in C, with a specific set of allowable function signatures, and using the name main() for anything else tends to break a lot of things. You probably want to use a name such as kmain() or something. I'm frankly surprised it compiled at all as it is - if you were using the recommended


I don't believe the standard puts any restrictions on main's prototype when compiling for a non-hosted environment using GCC's -ffreestanding option


OK, fair point; I really don't know either way, as it has always been one of the "Here There Be Nasal Demons" parts of the standard. A lot of things are left to implementors once you are talking about code which is by definition non-portable.

I'd still recommend using a different function name, even if it is technically permissible.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 44 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: SemrushBot [Bot] and 100 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:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group