Advertisement
Guest User

v2 board

a guest
Apr 25th, 2014
560
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <time.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <sys/mman.h>
  10. #include <sys/time.h>
  11.                            
  12. #define GPIO_ADD    0x20200000L // physical address of I/O peripherals on the ARM processor
  13. #define GPIO_SEL1   1           // Offset of SEL register for GP17 & GP18 into GPIO bank  
  14. #define GPIO_SEL2   2           // Offset of SEL register for GP21 into GPIO bank  
  15. #define GPIO_SET    7           // Offset of PIN HIGH register into GPIO bank  
  16. #define GPIO_CLR    10          // Offset of PIN LOW register into GPIO bank  
  17. #define GPIO_INP    13          // Offset of PIN INPUT value register into GPIO bank  
  18. #define PAGE_SIZE   4096        
  19. #define BLOCK_SIZE  PAGE_SIZE
  20.  
  21. /* RTC Chip register definitions */
  22. #define SEC_WRITE    0x80
  23. #define MIN_WRITE    0x82
  24. #define HOUR_WRITE   0x84
  25. #define DATE_WRITE   0x86
  26. #define MONTH_WRITE  0x88
  27. #define YEAR_WRITE   0x8C
  28. #define SEC_READ     0x81
  29. #define MIN_READ     0x83
  30. #define HOUR_READ    0x85
  31. #define DATE_READ    0x87
  32. #define MONTH_READ   0x89
  33. #define YEAR_READ    0x8D
  34.  
  35.  
  36. int  mem_fd     = 0;
  37. char *gpio_mmap = NULL;
  38. char *gpio_ram  = NULL;
  39. volatile unsigned int *gpio = NULL;
  40.  
  41.  
  42. /* These 'defines' map the peripheral pin functions to our circuits DS1302 pins */
  43. /* See DS1302 datasheet REV: 110805, and Broadcom BCM2835-ARM-Peripherals.pdf 6/2/2012 */
  44. #define IO_INPUT    *(gpio+GPIO_SEL1) &= 0xF8FFFFFFL
  45. #define IO_OUTPUT   *(gpio+GPIO_SEL1) &= 0xF8FFFFFFL; *(gpio+GPIO_SEL1) |= 0x01000000L
  46. #define SCLK_OUTPUT *(gpio+GPIO_SEL2) &= 0xFF1FFFFFL; *(gpio+GPIO_SEL2) |= 0x00200000L
  47. #define CE_OUTPUT   *(gpio+GPIO_SEL1) &= 0xFF1FFFFFL; *(gpio+GPIO_SEL1) |= 0x00200000L
  48. #define IO_HIGH     *(gpio+GPIO_SET) = 0x00040000L
  49. #define IO_LOW      *(gpio+GPIO_CLR) = 0x00040000L
  50. #define SCLK_HIGH   *(gpio+GPIO_SET) = 0x08000000L
  51. #define SCLK_LOW    *(gpio+GPIO_CLR) = 0x08000000L
  52. #define CE_HIGH     *(gpio+GPIO_SET) = 0x00020000L  
  53. #define CE_LOW      *(gpio+GPIO_CLR) = 0x00020000L
  54. #define IO_LEVEL    *(gpio+GPIO_INP) & 0x00040000L
  55.  
  56.  
  57. void setup_io()
  58. {
  59.  
  60.    /* open /dev/mem to get acess to physical ram */
  61.    if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
  62.       printf("can't open /dev/mem. Did you run the program with administrator rights?\n");
  63.       exit (-1);
  64.    }
  65.  
  66.    /* Allocate a block of virtual RAM in our application's address space */
  67.    if ((gpio_ram = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
  68.       printf("allocation error \n");
  69.       exit (-1);
  70.    }
  71.  
  72.    /* Make sure the pointer is on 4K boundary */
  73.    if ((unsigned long)gpio_ram % PAGE_SIZE)
  74.      gpio_ram += PAGE_SIZE - ((unsigned long)gpio_ram % PAGE_SIZE);
  75.  
  76.    /* Now map the physical addresses of the peripheral control registers
  77.       into our address space */
  78.    gpio_mmap = (unsigned char *)mmap(
  79.       (caddr_t)gpio_ram,
  80.       BLOCK_SIZE,
  81.       PROT_READ|PROT_WRITE,
  82.       MAP_SHARED|MAP_FIXED,
  83.       mem_fd,
  84.       GPIO_ADD
  85.    );
  86.  
  87.    if ((long)gpio_mmap < 0) {
  88.       printf("unable to map the memory. Did you run the program with administrator rights?\n");
  89.       exit (-1);
  90.    }
  91.  
  92.    /* Always use a volatile pointer to hardware registers */
  93.    gpio = (volatile unsigned *)gpio_mmap;
  94.  
  95.    /* Now we have access to the hardware reigsters we can start twiddling I/O pins */
  96.  
  97.    /* Switch GPIO 0, 1 and 2 to output mode */
  98.    SCLK_OUTPUT;
  99.    IO_OUTPUT;
  100.    CE_OUTPUT;
  101.  
  102.    /* Set the SCLK, IO and CE pins to default (low) */
  103.    SCLK_LOW;
  104.    IO_LOW;
  105.    CE_LOW;
  106.  
  107.    /* Short delay to allow the I/O lines to settle. */
  108.    usleep(2);
  109. }
  110.  
  111.  
  112. unsigned char read_rtc( unsigned char add )
  113. {
  114.    unsigned char val;
  115.    int lp;
  116.  
  117.    val = add;
  118.  
  119.    /* Check LSB is set */
  120.    if ( !(add & 1 ) ) {
  121.       printf("Incorrect read address specified - LSB must be set.\n");
  122.       exit (-1);
  123.    }
  124.  
  125.    /* Check address range is valid */
  126.    if ( (add < 0x81) || (add > 0x91) ) {
  127.       printf("Incorrect read address specified - It must be in the range 0x81..0x91\n");
  128.       exit (-1);
  129.    }
  130.  
  131.    CE_HIGH;
  132.  
  133.    usleep(2);
  134.  
  135.    for (lp=0; lp<8; lp++) {
  136.       if (val & 1)
  137.          IO_HIGH;
  138.       else
  139.          IO_LOW;
  140.       val >>= 1;
  141.       usleep(2);
  142.       SCLK_HIGH;
  143.       usleep(2);
  144.       SCLK_LOW;
  145.       usleep(2);    
  146.    }
  147.  
  148.    IO_INPUT;
  149.  
  150.    for (lp=0; lp<8; lp++) {
  151.       usleep(2);
  152.       val >>= 1;
  153.       if (IO_LEVEL)
  154.          val |= 0x80;
  155.       else
  156.          val &= 0x7F;        
  157.       SCLK_HIGH;
  158.       usleep(2);
  159.       SCLK_LOW;
  160.       usleep(2);
  161.    }
  162.  
  163.    /* Set the I/O pin back to it's default, output low. */
  164.    IO_LOW;
  165.    IO_OUTPUT;
  166.  
  167.    /* Set the CE pin back to it's default, low */
  168.    CE_LOW;
  169.  
  170.    /* Short delay to allow the I/O lines to settle. */
  171.    usleep(2);    
  172.  
  173.    return val;
  174. }
  175.  
  176.  
  177. void write_rtc( unsigned char add, unsigned char val_to_write )
  178. {
  179.    unsigned char val;
  180.    int lp;
  181.  
  182.    /* Check LSB is clear */
  183.    if ( add & 1 ) {
  184.       printf("Incorrect write address specified - LSB must be cleared.\n");
  185.       exit (-1);
  186.    }
  187.  
  188.    /* Check address range is valid */
  189.    if ( (add < 0x80) || (add > 0x90) ) {
  190.       printf("Incorrect write address specified - It must be in the range 0x80..0x90\n");
  191.       exit (-1);
  192.    }
  193.  
  194.    CE_HIGH;
  195.  
  196.    usleep(2);
  197.  
  198.    val = add;
  199.  
  200.    for (lp=0; lp<8; lp++) {
  201.       if (val & 1)
  202.          IO_HIGH;
  203.       else
  204.          IO_LOW;
  205.       val >>= 1;
  206.       usleep(2);
  207.       SCLK_HIGH;
  208.       usleep(2);
  209.       SCLK_LOW;
  210.       usleep(2);    
  211.    }
  212.  
  213.    val = val_to_write;
  214.  
  215.    for (lp=0; lp<8; lp++) {
  216.       if (val & 1)
  217.          IO_HIGH;
  218.       else
  219.          IO_LOW;
  220.       val >>= 1;
  221.       usleep(2);
  222.       SCLK_HIGH;
  223.       usleep(2);
  224.       SCLK_LOW;
  225.       usleep(2);    
  226.    }
  227.  
  228.    /* Set the I/O pin back to it's default, output low. */
  229.    IO_LOW;
  230.  
  231.    /* Set the CE pin back to it's default, low */
  232.    CE_LOW;
  233.  
  234.    /* Short delay to allow the I/O lines to settle. */
  235.    usleep(2);    
  236. }
  237.  
  238.  
  239. int main(int argc, char **argv)
  240. {
  241.    int lp;
  242.    unsigned char val;
  243.    int year,month,day,hour,minute,second;
  244.    time_t epoch_time;
  245.    struct tm time_requested;
  246.    struct timeval time_setformat;
  247.    
  248.    /* Check that the program was called correctly */
  249.    if ( argc > 2 ) {
  250.       printf("Too many arguments specified.\nRun as:\nrtc-pi\nor\nrtc-pi CCYYMMDDHHMMSS\n");
  251.       exit (-1);
  252.    }
  253.  
  254.    /* Set up gpi pointer for direct register access */
  255.    setup_io();
  256.      
  257.    if ( argc == 2 ) {
  258.       /* If the number of arguments are two, that means the user enter a date & time. */
  259.       /* Read that value and write it to the RTC chip */
  260.  
  261.       sscanf(argv[1],"%4d%2d%2d%2d%2d%2d",&year,&month,&day,&hour,&minute,&second);
  262.      
  263.       /* Validate that the input date and time is basically sensible */
  264.       if ( (year < 2000) || (year > 2099) || (month < 1) || (month > 12) ||
  265.             (day < 1) || (day>31) || (hour < 0) || (hour > 23) || (minute < 0) ||
  266.             (minute > 59) || (second < 0) || (second > 59) ) {
  267.          printf("Incorrect date and time specified.\nRun as:\nrtc-pi\nor\nrtc-pi CCYYMMDDHHMMSS\n");
  268.          exit (-1);
  269.       }
  270.  
  271.       /* Got valid input - now write it to the RTC */
  272.       /* The RTC expects the values to be written in packed BCD format */
  273.       write_rtc(SEC_WRITE, ( (second/10) << 4) | ( second % 10) );
  274.       write_rtc(MIN_WRITE, ( (minute/10) << 4) | ( minute % 10) );
  275.       write_rtc(HOUR_WRITE, ( (hour/10) << 4) | ( hour % 10) );
  276.       write_rtc(DATE_WRITE, ( (day/10) << 4) | ( day % 10) );
  277.       write_rtc(MONTH_WRITE, ( (month/10) << 4) | ( month % 10) );
  278.       write_rtc(YEAR_WRITE, ( ((year-2000)/10) << 4) | (year % 10) );  
  279.  
  280.       /* Finally convert to it to EPOCH time, ie the number of seconds since January 1st 1970, and set the system time */
  281.       time_requested.tm_sec = second;
  282.       time_requested.tm_min = minute;
  283.       time_requested.tm_hour = hour;
  284.       time_requested.tm_mday = day;
  285.       time_requested.tm_mon = month-1;
  286.       time_requested.tm_year = year-1900;
  287.       time_requested.tm_wday = 0; /* not used */
  288.       time_requested.tm_yday = 0; /* not used */
  289.       time_requested.tm_isdst = -1; /* determine daylight saving time from the system */
  290.      
  291.       epoch_time = mktime(&time_requested);
  292.      
  293.       /* Now set the clock to this time */
  294.       time_setformat.tv_sec = epoch_time;
  295.       time_setformat.tv_usec = 0;
  296.  
  297.       lp = settimeofday(&time_setformat,NULL);
  298.  
  299.       /* Check that the change was successful */
  300.       if ( lp < 0 ) {  
  301.          printf("Unable to change the system time. Did you run the program as an administrator?\n");
  302.          printf("The operation returned the error message \"%s\"\n", strerror( errno ) );
  303.          exit (-1);
  304.       }
  305.      
  306.    } else {
  307.       /* The program was called without a date specified; therefore read the date and time from */
  308.       /* the RTC chip and set the system time to this */
  309.       second = read_rtc(SEC_READ);
  310.       minute = read_rtc(MIN_READ);
  311.       hour = read_rtc(HOUR_READ);
  312.       day = read_rtc(DATE_READ);
  313.       month = read_rtc(MONTH_READ);
  314.       year = read_rtc(YEAR_READ);  
  315.  
  316.       /* Finally convert to it to EPOCH time, ie the number of seconds since January 1st 1970, and set the system time */
  317.       /* Bearing in mind that the format of the time values in the RTC is packed BCD, hence the conversions */
  318.  
  319.       time_requested.tm_sec = (((second & 0x70) >> 4) * 10) + (second & 0x0F);
  320.       time_requested.tm_min = (((minute & 0x70) >> 4) * 10) + (minute & 0x0F);
  321.       time_requested.tm_hour = (((hour & 0x30) >> 4) * 10) + (hour & 0x0F);
  322.       time_requested.tm_mday = (((day & 0x30) >> 4) * 10) + (day & 0x0F);
  323.       time_requested.tm_mon = (((month & 0x10) >> 4) * 10) + (month & 0x0F) - 1;
  324.       time_requested.tm_year = (((year & 0xF0) >> 4) * 10) + (year & 0x0F) + 2000 - 1900;
  325.       time_requested.tm_wday = 0; /* not used */
  326.       time_requested.tm_yday = 0; /* not used */
  327.       time_requested.tm_isdst = -1; /* determine daylight saving time from the system */
  328.      
  329.       epoch_time = mktime(&time_requested);
  330.      
  331.       /* Now set the clock to this time */
  332.       time_setformat.tv_sec = epoch_time;
  333.       time_setformat.tv_usec = 0;
  334.  
  335.       lp = settimeofday(&time_setformat,NULL);
  336.  
  337.       /* Check that the change was successful */
  338.       if ( lp < 0 ) {  
  339.          printf("Unable to change the system time. Did you run the program as an administrator?\n");
  340.          printf("The operation returned the error message \"%s\"\n", strerror( errno ) );
  341.          exit (-1);
  342.       }
  343.    }
  344.  
  345.    return 0;
  346. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement