Разработка драйвера для Linux: драйвер часов реального времени RTC под Linux
Разработка драйвера для Linux: драйвер часов реального времени RTC под Linux

Версия ядра Linux: 3.5

1.1 Чтение и запись анализа времени RTC в Linux

1.1.1 Системное время и время часов реального времени RTC

Система Linux содержит два времени: системное время и время RTC.

Системное время: это время, поддерживаемое таймером основного чипа. Как правило, в качестве основы синхронизации системного времени выбирается наиболее точный таймер на чипе, чтобы избежать больших отклонений во времени после длительной работы системы. . Особенность в том, что он не сохраняется после выключения питания.

Время RTC: относится к времени, поддерживаемому внутри чипа RTC, включенного в систему. Чип RTC имеет двойной механизм питания: батарея + питание системы. Когда система работает нормально, она питается от системы, а когда система выключена, она питается от батареи. Таким образом, время RTC может продолжать работать нормально после отключения питания системы.

Каждый раз при запуске системы Linux драйвер RTC будет обнаруживаться и монтироваться в процессе запуска. После монтирования время будет автоматически считываться с чипа RTC и устанавливаться на системное время. Впоследствии, если нет явной команды для управления операциями чтения и записи часов реального времени, система больше не будет получать или синхронизировать время установки от часов реального времени.

Такие команды, как дата и время в командах Linux, используются для установки системного времени.,иhwclockКоманды используются для установки, чтения и записи.RTCвременный。

1.1.2 Просмотр и выбор конфигурации часов реального времени RTC ядра Linux:

Войдите в корневой каталог ядра и введите: make Menuconfig, чтобы войти в меню конфигурации ядра:

Войдите в меню драйвера реального времени RTC согласно параметрам:

Язык кода:javascript
копировать
Device Drivers  --->        [*] Real Time Clock  --->                --- Real Time Clock                                                    │ │    │ │    [*]   Set system time from RTC on startup and resume                   │ │    │ │    (rtc0)  RTC used to set the system time                                │ │    │ │    [ ]   RTC debug support                                                │ │    │ │          *** RTC interfaces ***                                           │ │    │ │    [*]   /sys/class/rtc/rtcN (sysfs)     [*]   /proc/driver/rtc (procfs for rtc0)                               │ │    │ │    [*]   /dev/rtcN (character devices)                                    │ │    │ │    [ ]     RTC UIE emulation on dev interface                             │ │    │ │    < >   Test driver/device                                               │ │    │ │          *** I2C RTC drivers ***                                          │ │    │ │    < >   Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025      < >   Dallas/Maxim DS1374                                              │ │    │ │    < >   Dallas/Maxim DS1672                                              │ │    │ │    < >   Dallas/Maxim DS3232                                              │ │    │ │    < >   Maxim MAX6900                                                    │ │    │ │    < >   Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A    < >   Intersil ISL1208                                                 │ │    │ │    < >   Intersil ISL12022                                                │ │    │ │    < >   Xicor/Intersil X1205                                             │ │    │ │    < >   Philips PCF8563/Epson RTC8564                                    │ │    │ │    < >   Philips PCF8583                                                  │ │    │ │    < >   ST M41T62/65/M41T80/81/82/83/84/85/87         < >   TI BQ32000                                                       │ │    │ │    < >   Seiko Instruments S-35390A                                       │ │    │ │    < >   Ramtron FM3130                                                   │ │    │ │    < >   Epson RX-8581                                                    │ │    │ │    < >   Epson RX-8025SA/NB                                               │ │    │ │    < >   EM Microelectronic EM3027    < >   Micro Crystal RTC                                                │ │    │ │          *** SPI RTC drivers ***                                          │ │    │ │    < >   ST M41T93                                                        │ │    │ │    < >   ST M41T94                                                        │ │    │ │    < >   Dallas/Maxim DS1305/DS1306                                       │ │    │ │    < >   Dallas/Maxim DS1390/93/94          *** Platform RTC drivers ***                                     │ │    │ │    < >   PC-style 'CMOS'                                                  │ │    │ │    < >   Dallas DS1286                                                    │ │    │ │    < >   Dallas DS1511                                                    │ │    │ │    < >   Maxim/Dallas DS1553            *** on-CPU RTC drivers ***                                       │ │    │ │    <*>   Samsung S3C series SoC RTC                                       │ │    │ │    < >   ARM AMBA PL030 RTC                                               │ │    │ │    < >   ARM AMBA PL031 RTC                                               │ │    │ └──────────────────────────────

В зависимости от конфигурации ядра известны три части информации (параметры конфигурации выделены красным):

1. Системное время по умолчанию получает время из RTC0 и устанавливает его.

(rtc0 представляет первый драйвер RTC в /dev. Если установлен второй драйвер RTC, он будет представлен как rtc1 и т. д.)

2. Используйте proc для просмотра информации RTC. По умолчанию ее можно получить только с узла rtc0 (первый драйвер RTC в системе).

Язык кода:javascript
копировать
[root@XiaoLong /]#cat /proc/driver/rtc

3. По умолчанию ядро ​​выбирает RTC, поставляемый с самим процессором, в качестве системных часов реального времени.

Исходный код драйвера\linux-3.5\drivers\rtc\ rtc-s3c.cЭто драйвер RTC, написанный Samsung.。

1.1.3 Знакомство с использованием команды даты

date — это команда, используемая для отображения или установки системной даты и времени.

Формат использования команды: date [параметр]... [+формат]

Параметры, которые может принимать команда, следующие:

Пример использования: date '+%A' Обязательные параметры: %H Часы (выражены как 00-23). %I Часы (выражены как 01-12). %K Часы (выражены как 0–23). %l Часы (выражены в цифрах 0–12). %M Минуты (выражены как 00-59). %P Утро или вечер. %r Время (включая часы, минуты и секунды, часы выражаются в 12-часовом формате AM/PM). %s Всего секунд. Время начала: 1 января 1970 г. 00:00:00 UTC。 %S Секунды (выраженные на местной идиоме). %T Время (включая часы, минуты и секунды, часы выражаются в 24-часовом формате). %X Время (выраженное на местной идиоме). %Z городской район. %a Аббревиатура недели. %A Полное название недели. %b Аббревиатура английского названия месяца. %B Полное английское название месяца. %c Дата и время. Ввод только команды даты приведет к тому же результату. %d Дата (выраженная как 01-31). %D Дата (включая год, месяц и день). %j День года. %m Месяц (выраженный как 01–12). %U Количество недель в году. %w Количество дней в неделе: 0 — воскресенье, 1 — понедельник и т. д. %x Дата (выраженная на местном языке). %y Год (выраженный как 00–99). %Y Год (выраженный четырьмя цифрами). %n При отображении вставьте новую строку. %t При отображении вставьте вкладки. MM Месяц (обязательно) DD Дата (обязательно) hh часы (обязательно) mm минут (обязательно) ss секунды (необязательно) Выберите параметры: -d<нить>  Отображает дату и время, на которые указывает строка. Строке должны предшествовать и следовать двойные кавычки. -s<нить>  Установите дату и время на основе строки. Строке должны предшествовать и следовать двойные кавычки. -u  Отображать время по Гринвичу. --help  Онлайн-помощь. --version  Показать информацию о версии

Режим системного времени

[root@XiaoLong /]# date -s "2018-07-28 14:21:22" //Установить все даты и время [root@XiaoLong /]# date -s "14:30:22" //Установить только Time [root@XiaoLong /]# date -s «2017-07-28» //Установка даты, время по умолчанию — 00:00:00

Пример формата

[root@XiaoLong /]# date -r app // Опция -r позволяет распечатать время последнего изменения указанного файла. Пт, 29 апреля, 05:17:34 UTC 2016 [root@XiaoLong /]# date -d 23: 39:00 //Распечатываем время в указанном формате (только эффект печати не имеет других эффектов) Сб, 30 апреля 23:39:00 UTC 2016 [root@XiaoLong /]# date -s 12:20:30 //Установим системное время на 12:20:30 Сб, 30 апреля 12:20:30 UTC 2016 [root@XiaoLong /]# date -s 2016.04.30-23:20:10 / /Установить системное время на 23:20:10 30 апреля 2016 г., суббота, 30 апреля. 23:20:10 UTC 2016

1.1.4 Получение и настройка системного времени RTC реального времени.

1. Синхронизируйте время RTC с системным временем.

[root@XiaoLong /]# hwclock -s

Чтобы автоматически синхронизировать время RTC с системным временем при запуске, вы можете добавить команду hwclock -s в профиль или файл rcS.

2. Получите и отобразите время RTC.

Язык кода:javascript
копировать
[root@XiaoLong /]# hwclock -r Sun May  1 00:09:36 2016  0.000000 seconds

3. Синхронизируйте системное время с RTC для установки времени.

Язык кода:javascript
копировать
[root@XiaoLong /]# hwclock -w

4. Просмотр информации RTC

Язык кода:javascript
копировать
[root@XiaoLong /]# cat /proc/driver/rtc rtc_time        : 00:09:27 rtc_date        : 2016-05-01 alrm_time       : 23:24:07 alrm_date       : 2016-05-01 alarm_IRQ       : no alrm_pending    : no update IRQ enabled      : no periodic IRQ enabled    : no periodic IRQ frequency  : 1 max user IRQ frequency  : 32768 24hr            : yes periodic_IRQ    : no

1.2 Структура подсистемы RTC ядра Linux

1.2.1 Основные документы, относящиеся к структуре РУЦ

1. /drivers/rtc/class.c Этот файл регистрирует класс RTC в ядре модели устройства Linux, а затем предоставляет драйверу интерфейс регистрации/отмены регистрации.

2. /drivers/rtc/rtc-dev.c Этот файл определяет основные функции работы с файлом устройства, такие как: открытие, чтение и т. д.

3. /drivers/rtc/interface.c Как следует из названия, этот файл в основном обеспечивает функции интерфейса между пользовательской программой и драйвером RTC. Пользовательская программа обычно взаимодействует с драйвером RTC через ioctl. по каждой команде ioctl определены здесь.

4. /drivers/rtc/rtc-sysfs.c связан с sysfs.

5. /drivers/rtc/rtc-proc.c связан с файловой системой proc.

6. /include/linux/rtc.h определяет структуры данных, относящиеся к RTC.

Место хранения кода драйвера RTC, который поставляется с исходным кодом ядра Linux:

Каталог \linux-3.5\drivers\rtc\ полон примеров кодов драйверов RTC. Среди них: rtc-s3c.c — драйвер RTC, написанный Samsung.

1.2.2 RTC, лежащие в основе функций регистрации и отмены регистрации, предоставляемые ядром

1. Функция регистрации структуры RTC

struct rtc_device *rtc_device_register( const char *name, //имя часов RTC struct device *dev, //указатель устройства. Этот указатель необходимо получить через устройство платформы. const struct rtc_class_ops *ops, //модуль структуры сбора операций с файлами rtc *владелец ) //Владелец драйвера. Заполните: THIS_MODULE

Пример использования: rtc_device_register("tiny4412_rtc",&pdev->dev, &tiny4412_rtcops,THIS_MODULE);

После успешной регистрации с помощью функции rtc_device_register,существовать/dev/Вы можете увидеть это нижеrtcxузел устройства(xдаrtcпорядковый номер)。

2. Функция выхода из системы RTC

Язык кода:javascript
копировать
void rtc_device_unregister(struct rtc_device *rtc)

После анализа формальных параметров функции регистрации RTC необходимо выполнить регистрацию подсистемы RTC через структуру платформенного устройства. Регистрация rtc выполняется в функции проверки на стороне драйвера платформенного устройства, а затем выполняется отмена регистрации. в функции удаления требования к оборудованию RTC передаются со стороны устройства RTC на сторону драйвера.

1.2.3 Интерфейс сбора файловых операций

rtc_class_ops Эта структура представляет собой базовую операционную функцию, реализуемую драйвером RTC. Драйвер связывает реализуемые им функции с ядром RTC, инициализируя такую ​​структуру. Большинство функций здесь должны быть реализованы драйвером. Более того, эти функции работают на базовом оборудовании и относятся к функциям самого низкого уровня. Этот интерфейс драйвера связан с командой hwclock прикладного уровня, а базовые функции RTC можно вызывать с помощью команды hwclock.

Язык кода:javascript
копировать
struct rtc_class_ops {        int (*open)(struct device *);  //Открыть        void (*release)(struct device *);        int (*ioctl)(struct device *, unsigned int, unsigned long);   /*функция ioctl*/        int (*read_time)(struct device *, struct rtc_time *);   //время чтения        int (*set_time)(struct device *, struct rtc_time *);    //Установим время        int (*read_alarm)(struct device *, struct rtc_wkalrm *);  //Читаем будильник        int (*set_alarm)(struct device *, struct rtc_wkalrm *);   //Установим будильник        int (*proc)(struct device *, struct seq_file *);          //интерфейс процесса        int (*set_mmss)(struct device *, unsigned long secs);    //Установим второй юнит        int (*read_callback)(struct device *, int data);          //функция обратного вызова        int (*alarm_irq_enable)(struct device *, unsigned int enabled);  //Включение прерывания будильника };

Драйверам в подсистеме RTC обычно требуется реализовать только функциональные интерфейсы для установки и получения времени. Пользователи могут передать соответствующую команду через функцию ioctl на уровне приложения, чтобы вызвать интерфейс уровня драйвера для получения и настройки времени.

Две часто используемые команды:

#define RTC_RD_TIME _IOR(RTC_MAGIC, 0x09, struct rtc_time) /* Чтение времени RTC */ #define RTC_SET_TIME _IOW(RTC_MAGIC, 0x0a, struct rtc_time) /* Установка времени RTC */ //Все поддерживаемые команды находятся в интерфейсе.c. В документации есть примеры использования. Эти команды можно использовать, когда пользователи пишут свой собственный код прикладного уровня. RTC_ALM_READ rtc_read_alarm Чтение времени сигнала RTC_ALM_SET rtc_set_alarm Установка времени сигнала RTC_RD_TIME rtc_read_time Чтение времени и даты RTC_SET_TIME rtc_set_time Установка времени и даты RTC_PIE_ON RTC_PIE_OFF rtc_irq_set_state Функция переключения глобального прерывания RTC RTC_AIE_ON RTC_AIE_OFF rtc_alarm_irq_enable Включение и отключение прерывания тревоги RTC RTC_UIE_OFF RTC_UIE_ON rtc_update_irq_enable Включение и отключение прерывания обновления RTC RTC_IRQP_SET rtc_irq_set_freq Установка частоты прерывания

1.2.4 Временная структура RTC

rtc_time представляет время и дату, записанные RTC. Время и дата, считанные с устройства RTC, хранятся в этой структуре.

Язык кода:javascript
копировать
struct rtc_time {        int tm_sec;  //Второй        int tm_min;  //минута        int tm_hour; //Час        int tm_mday; //небо        int tm_mon;  //луна        int tm_year;  //Год        int tm_wday; //день недели        int tm_yday; //Один день в году        int tm_isdst; //Действительно летнее время };

1.2.5 Структура будильника

Язык кода:javascript
копировать
struct rtc_wkalrm {        unsigned char enabled;   /* Переключатель включения будильника    0 = alarm disabled, 1 = alarm enabled */        unsigned char pending;  /* Статус обработки сигнала будильника 0 = alarm not pending не производится, 1 = alarm pending Генерируется сигнал тревоги*/        struct rtc_time time;       /* Время установки будильника */ };

1.3 Запись кода драйвера RTC

1.3.1 Подготовка

Чтобы протестировать собственный драйвер RTC, вам необходимо заранее удалить драйвер RTC, идущий в комплекте с ядром, перекомпилировать и запрограммировать ядро, а затем установить и протестировать его.

На примере платы разработки tiny4412 удалите встроенный драйвер rtc.

1. Войдите в меню конфигурации ядра: make menuconfig

Язык кода:javascript
копировать
  Device Drivers  --->
       [*] Real Time Clock  --->

2. Перекомпилируем ядро, а затем перепрограммируем ядро ​​на SD или EMMC:

[root@wbyq boot]# ./123.sh записано 9288+1 операций чтения и записано 9288+1 операций записи, скопировано 4755752 байта (4,8 МБ), 33,2798 секунды, 143 КБ/сек.

По умолчанию без драйвера RTC системное время получается начиная с 1970 года:

1.3.2 Написание кода драйвера RTC — пример платформы

Следующий код демонстрирует только структуру регистрации на основе RTC.

1. Код устройства RTC:

Язык кода:javascript
копировать
#include "linux/module.h"
#include "linux/init.h"
#include <linux/platform_device.h>
/*
 * device  Сторона устройства
 */

//Освобождаем шину платформы
static void pdev_release(struct device *dev)
{
	printk("rtc_pdev:the rtc_pdev is close!!!\n");
}

/*Сторона устройства Структура*/
struct platform_device  rtc_pdev= /*Структура устройства, имя устройства очень важно!*/
{
	.name = "tiny4412rtc",  /*Имя устройства*/
	.id = -1,         /*-1 означает, что имя устройства здесь будет указано после успешного создания. Если значение равно 0 или 1, имя устройства будет myled.0, myled.1...*/.
	.dev =            /*Вызывается при удалении драйвера*/
	{
		.release = pdev_release,/*Освободить ресурсы*/
	},
};


/*платформа Сторона функция входа в устройство*/
static int __init plat_dev_init(void)
{
	platform_device_register(&rtc_pdev);/*зарегистрироватьсяплатформа Сторона устройства*/
	return 0;
}

/*платформа Сторона функция экспорта устройства */
static void __exit plat_dev_exit(void)
{
	platform_device_unregister(&rtc_pdev);/*Выйтиплатформа Сторона устройства*/
}

module_init(plat_dev_init);
module_exit(plat_dev_exit);
MODULE_LICENSE("GPL");

2. Код драйвера RTC

Язык кода:javascript
копировать
#include <linux/module.h>             /*Связано с модулем привода*/
#include <linux/init.h>
#include <linux/fs.h>                 /*Коллекция файловых операций*/
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>          /*Файлы заголовков, связанные с прерываниями*/
#include <linux/irq.h>                /*Файлы заголовков, связанные с прерываниями*/
#include <linux/gpio.h>               /*Аппаратное обеспечение->Имена и адреса регистров определены*/
#include <linux/wait.h>              
#include <linux/sched.h>
#include <linux/timer.h>              /*Таймер ядра*/
#include <asm-generic/poll.h>         
#include <linux/poll.h>               /* механизм опроса*/
#include <linux/platform_device.h>    /* Заголовочные файлы, связанные с драйверами устройств платформы*/
#include <linux/rtc.h>

static int tiny4412_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
	printk("Время получено успешно\n");
	return 0;
}

static int tiny4412_rtc_settime(struct device *dev, struct rtc_time *tm)
{
	printk("Время установлено успешно\n");
	return 0;	
}

static int tiny4412_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	printk("Вызов getalarm успешен\n");
	return 0;	
}

static int tiny4412_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	printk("Вызов getalarm успешен\n");
	return 0;	
}
	
static int tiny4412_rtc_proc(struct device *dev, struct seq_file *seq)
{
	printk("вызов процедуры успешен\n");
	return 0;	
}

static int tiny4412_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	printk("alarm_irq_enable был успешно вызван\n");
	return 0;	
}

static int tiny4412_rtc_ioctl(struct device *dev, unsigned int cmd,unsigned long arg)
{
	printk("вызов ioctl успешен\n");
	return 0;
}


/*Операция с файлом RTC*/
static const struct rtc_class_ops tiny4412_rtcops = {
	.read_time	= tiny4412_rtc_gettime,
	.set_time	= tiny4412_rtc_settime,
	.read_alarm	= tiny4412_rtc_getalarm,
	.set_alarm	= tiny4412_rtc_setalarm,
	.proc		= tiny4412_rtc_proc,
	.alarm_irq_enable = tiny4412_rtc_alarm_irq_enable,
	.ioctl		= tiny4412_rtc_ioctl,
};

struct rtc_device *rtc=NULL;

/*Функция, которая успешно выполняется при совпадении устройства — функция исследования ресурса*/
static int drv_probe(struct platform_device *pdev)
{	
	rtc = rtc_device_register("tiny4412_rtc",&pdev->dev, &tiny4412_rtcops,THIS_MODULE);
	if(rtc==NULL)
	printk("Ошибка регистрации драйвера RTC\n");
	else
  	{
  		printk("Регистрация драйвера RTC прошла успешно\n");
  	}         
	return 0;
}

static int drv_remove(struct platform_device *dev)/*Эта функция вызывается при удалении устройства*/
{
	rtc_device_unregister(rtc);
	printk("Драйвер RTC успешно удален\n");
	return 0;
}


/*Структура драйвера устройства платформы — содержит имя устройства, соответствующее зонду*/
struct platform_driver  drv= 
{
	.probe = drv_probe,    /*Необходимо создать функцию зонда, которая будет управлять устройством*/
	.remove = drv_remove,  /*Создаем функцию удаления для выхода из устройства*/
	.driver = 
	{
		.name = "tiny4412rtc",/*Имя устройства,используется с Сторона устройствоматч (очень важно)*/
	},
};

/*Функция входа драйвера платформы*/
static int __init plat_drv_init(void)
{
	platform_driver_register(&drv);/*зарегистрироватьсяплатформаводить машину*/	
	return 0;
}

/*Функция экспорта драйвера платформы*/
static void __exit plat_drv_exit(void)
{
	platform_driver_unregister(&drv);/*выпускатьплатформаводить машину*/
}

module_init(plat_drv_init);  /*Вход модуля драйвера*/
module_exit(plat_drv_exit);  /*Экспорт модуля драйвера*/
MODULE_LICENSE("GPL"); /*Положение о водительских правах*/

3. Установите драйвер RTC.

4. Просмотр узла устройства сгенерированного RTC.

5. Просмотр информации о RTC

При просмотре файла /proc/driver/rtc интерфейсы функций базового драйвера также вызываются один за другим. Однако только что написанный драйвер RTC не идеален, поэтому полученная информация неверна и является значением по умолчанию.

6. Установите тесты команд, связанные со временем RTC.

Посредством тестирования команд как установка времени, так и получение времени вызывают базовый интерфейс функции RTC, а оставшаяся работа заключается в улучшении кода драйвера.

1.3.3 Улучшение драйвера RTC

Предыдущий шаг завершил написание структуры кода драйвера RTC. На этом этапе мы не добавляем аппаратный код RTC и используем программное обеспечение для имитации передачи времени на прикладной уровень.

Примечание. Преобразование времени RTC в ядре рассчитывается от: 1900, а месяц начинается с 0.

При присвоении значения структуре rtc нужно вычесть 1900 из обычного года и 1 из месяца.

Пример назначения:

Язык кода:javascript
копировать
//Эту функцию можно вызвать через команду RTC_RD_TIME ioctl прикладного уровня
static int tiny4412_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
	rtc_tm->tm_year=2018-1900;   //Год 
	rtc_tm->tm_mon=8-1;         //луна 
	rtc_tm->tm_mday=18;         //день 
	rtc_tm->tm_hour=18;		   //час 
	rtc_tm->tm_min=18;		//точка 
	rtc_tm->tm_sec=18;//Второй
	printk("Успешно получено время с нижнего уровня RTC!\n");
	return 0;
}

Время, полученное прикладным уровнем, выглядит следующим образом:

Улучшенный код драйвера устройства RTC.

Язык кода:javascript
копировать
#include <linux/module.h>             /*Связано с модулем привода*/
#include <linux/init.h>
#include <linux/fs.h>                 /*Коллекция файловых операций*/
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>          /*Файлы заголовков, связанные с прерываниями*/
#include <linux/irq.h>                /*Файлы заголовков, связанные с прерываниями*/
#include <linux/gpio.h>               /*Аппаратное обеспечение->Имена и адреса регистров определены*/
#include <linux/wait.h>              
#include <linux/sched.h>
#include <linux/timer.h>              /*Таймер ядра*/
#include <asm-generic/poll.h>         
#include <linux/poll.h>               /* механизм опроса*/
#include <linux/platform_device.h>    /* Заголовочные файлы, связанные с драйверами устройств платформы*/
#include <linux/rtc.h>

//Эту функцию можно вызвать через команду RTC_RD_TIME ioctl прикладного уровня
static int tiny4412_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
	rtc_tm->tm_year=2018-1900;   //Год 
	rtc_tm->tm_mon=8-1;     //луна 
	rtc_tm->tm_mday=18;   //день 
	rtc_tm->tm_hour=18;		//час 
	rtc_tm->tm_min=18;		//точка 
	rtc_tm->tm_sec=18;//Второй
	printk("Успешно получено время с нижнего уровня RTC!\n");
	return 0;
}

//Эту функцию можно вызвать через команду RTC_SET_TIME ioctl уровня приложения
static int tiny4412_rtc_settime(struct device *dev, struct rtc_time *tm)
{
    printk("Время получения RTC: %d-%d-%d %d-%d-%d\n",1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
		 tm->tm_hour, tm->tm_min, tm->tm_sec);
	return 0;	
}

//Получаем время будильника
static int tiny4412_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	alrm->enabled=0;  //Будильник по умолчанию выключен
    alrm->time.tm_year=2018-1900;  //Год 
	alrm->time.tm_mon=8-1;    //луна 
	alrm->time.tm_mday=18;  //день 
	alrm->time.tm_hour=18;	//час 
	alrm->time.tm_min=18;	//точка 
	alrm->time.tm_sec=18;	//Второй
	printk("Успешно получено время будильника с нижнего уровня RTC!\n");
	return 0;	
}

//Установить время будильника
static int tiny4412_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	printk("Будильник RTC установлен успешно\n");
	return 0;	
}

//интерфейс процессавызов
static int tiny4412_rtc_proc(struct device *dev, struct seq_file *seq)
{
	printk("вызов процедуры успешен\n");
	return 0;	
}

//Включение прерывания будильника
static int tiny4412_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	printk("alarm_irq_enable был успешно вызван\n");
	return 0;	
}

//Может реализовывать пользовательские команды
static int tiny4412_rtc_ioctl(struct device *dev, unsigned int cmd,unsigned long arg)
{
	printk("вызов ioctl успешен\n");
	return 0;
}

/*Операция с файлом RTC*/
static const struct rtc_class_ops tiny4412_rtcops = {
	.read_time	= tiny4412_rtc_gettime,
	.set_time	= tiny4412_rtc_settime,
	.read_alarm	= tiny4412_rtc_getalarm,
	.set_alarm	= tiny4412_rtc_setalarm,
	.proc		= tiny4412_rtc_proc,
	.alarm_irq_enable = tiny4412_rtc_alarm_irq_enable,
	.ioctl		= tiny4412_rtc_ioctl,
};

struct rtc_device *rtc=NULL;

/*Функция, которая успешно выполняется при совпадении устройства — функция исследования ресурса*/
static int drv_probe(struct platform_device *pdev)
{	
	rtc = rtc_device_register("tiny4412_rtc",&pdev->dev, &tiny4412_rtcops,THIS_MODULE);
	if(rtc==NULL)
	printk("Ошибка регистрации драйвера RTC\n");
	else
  	{
  		printk("Регистрация драйвера RTC прошла успешно\n");
  	}         
	return 0;
}

static int drv_remove(struct platform_device *dev)/*Эта функция вызывается при удалении устройства*/
{
	rtc_device_unregister(rtc);
	printk("Драйвер RTC успешно удален\n");
	return 0;
}

/*Структура драйвера устройства платформы — содержит имя устройства, соответствующее зонду*/
struct platform_driver  drv= 
{
	.probe = drv_probe,    /*Необходимо создать функцию зонда, которая будет управлять устройством*/
	.remove = drv_remove,  /*Создаем функцию удаления для выхода из устройства*/
	.driver = 
	{
		.name = "tiny4412rtc",/*Имя устройства,используется с Сторона устройствоматч (очень важно)*/
	},
};

/*Функция входа драйвера платформы*/
static int __init plat_drv_init(void)
{
	platform_driver_register(&drv);/*зарегистрироватьсяплатформаводить машину*/	
	return 0;
}

/*Функция экспорта драйвера платформы*/
static void __exit plat_drv_exit(void)
{
	platform_driver_unregister(&drv);/*выпускатьплатформаводить машину*/
}

module_init(plat_drv_init);  /*Вход модуля драйвера*/
module_exit(plat_drv_exit);  /*Экспорт модуля драйвера*/
MODULE_LICENSE("GPL"); /*Положение о водительских правах*/

Результаты испытаний установки:

Язык кода:javascript
копировать
[root@XiaoLong /code]# date
Thu Jan  1 00:00:13 UTC 1970
[root@XiaoLong /code]# insmod plat_rtc_device.ko 
[root@XiaoLong /code]# insmod plat_rtc_drver.ko 
[   24.350000] Получение времени от нижнего уровня RTC успешно!
[   24.350000] Успешно получено время будильника с нижнего уровня RTC!
[   24.350000] Получение времени от нижнего уровня RTC успешно!
[   24.350000] tiny4412rtc tiny4412rtc: rtc core: registered tiny4412_rtc as rtc0
[   24.350000] Регистрация драйвера RTC прошла успешно
[root@XiaoLong /code]# cat /proc/driver/rtc 
[   37.085000] Получение времени от нижнего уровня RTC успешно!
[   37.085000] вызов процедуры успешен
rtc_time        : 18:18:18
rtc_date        : 2018-08-18
alrm_time       : 18:18:18
alrm_date       : 2018-08-18
alarm_IRQ       : no
alrm_pending    : no
update IRQ enabled      : no
periodic IRQ enabled    : no
periodic IRQ frequency  : 1
max user IRQ frequency  : 64
24hr            : yes
[root@XiaoLong /code]# 
[root@XiaoLong /code]# hwclock -s
[   58.600000] Получение времени от нижнего уровня RTC успешно!
[root@XiaoLong /code]# hwclock -r
[   61.020000] Получение времени от нижнего уровня RTC успешно!
Sat Aug 18 18:18:18 2018  0.000000 seconds
[root@XiaoLong /code]# hwclock -w
[   62.920000] Время получения RTC: 18 июля 2018 г. 18-18-22
[   62.920000] Получение времени от нижнего уровня RTC успешно!
[   62.920000] Alarm_irq_enable был успешно вызван
[root@XiaoLong /code]# date
Sat Aug 18 18:18:24 UTC 2018

1.3.4 Код прикладного уровня RTC

Если уровень приложения хочет взаимодействовать с драйвером RTC, он может использовать некоторые команды, специфичные для функции ioctl.

Обычно используемые команды ioctl в подсистеме RTC:

Язык кода:javascript
копировать
//Все поддерживаемые команды Примеры использования есть в файлеinterface.c. Эти команды можно использовать, когда пользователи сами пишут код прикладного уровня.
RTC_ALM_READ                     rtc_read_alarm        Прочитать время будильника
RTC_ALM_SET                      rtc_set_alarm          Установить время будильника
RTC_RD_TIME                      rtc_read_time          Чтение времени и даты
RTC_SET_TIME                     rtc_set_time            Установите время и дату
RTC_PIE_ON RTC_PIE_OFF           rtc_irq_set_state         Функция включения и выключения глобального прерывания RTC
RTC_AIE_ON RTC_AIE_OFF           rtc_alarm_irq_enable     Включение и отключение прерывания тревоги RTC
RTC_UIE_OFF RTC_UIE_ON           rtc_update_irq_enable    Включить и отключить прерывание обновления RTC
RTC_IRQP_SET                       rtc_irq_set_freq           Установить частоту прерываний

Пример кода:

Язык кода:javascript
копировать
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/rtc.h>
struct rtc_time time; //сохраняем значение времени

int main(int argc,char **argv)
{
	if(argc!=2)
	{
		printf("Формат параметра:/dev/rtc\r\n");
		return;
	}
	int fd=open(argv[1],O_RDWR); // 2==O_RDWR
	if(fd<0)
	{
		printf("Не удалось открыть файл драйвера устройства!\r\n");
		return 0;
	}
	
	time.tm_year=2017;
	time.tm_mon=10;
	time.tm_mday=13;
	time.tm_hour=21;
	time.tm_min=10;
	time.tm_sec=10;
	
	
	//Примечание: год, месяц и день должны быть заполнены обычным образом, иначе базовая функция не будет успешно вызвана.
    ioctl(fd,RTC_SET_TIME,&time);   //Нижний уровень реализует функцию ioctl и устанавливает время RTC
	while(1)
	{
		ioctl(fd,RTC_RD_TIME,&time);
		printf("%d-%d-%d %d:%d:%d\r\n",time.tm_year,time.tm_mon,time.tm_mday,time.tm_hour,time.tm_min,time.tm_sec);
		sleep(1);
	}
}

1.3.5 Функция преобразования стандартного времени в секунды

Некоторые аппаратные настройки часов реального времени RTC отсчитывают только секунды и не обеспечивают настройки времени в формате года, месяца, дня, часа, минуты и секунды. В этом случае вам необходимо самостоятельно преобразовать стандартное время.

Преобразование стандартного времени в секунды:

Язык кода:javascript
копировать
/*
 * С 01.01.1970 года происходит перевод дат по григорианскому календарю в секунды.
 */
int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
{
	*time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
			tm->tm_hour, tm->tm_min, tm->tm_sec);
	return 0;
}

1.3.6 Пример написания драйвера тактового чипа DS1302

Все приведенные выше коды представляют собой аналоговые часы. Чтобы узнать, как использовать структуру RTC, следующие коды добавляют фактическое оборудование RTC для достижения полной синхронизации RTC.

Код драйвера DS1302:

Язык кода:javascript
копировать
#include <linux/module.h>             /*Связано с модулем привода*/
#include <linux/init.h>
#include <linux/fs.h>                 /*Коллекция файловых операций*/
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>          /*Файлы заголовков, связанные с прерываниями*/
#include <linux/irq.h>                /*Файлы заголовков, связанные с прерываниями*/
#include <linux/gpio.h>               /*Аппаратное обеспечение->Имена и адреса регистров определены*/
#include <linux/wait.h>              
#include <linux/sched.h>
#include <linux/timer.h>              /*Таймер ядра*/
#include <asm-generic/poll.h>         
#include <linux/poll.h>               /* механизм опроса*/
#include <linux/platform_device.h>    /* Заголовочные файлы, связанные с драйверами устройств платформы*/
#include <linux/rtc.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/delay.h>

/*--------------------------------Коды операций, связанные с DS1302------------ ----------------------------------*/
static unsigned char RTC_bin2bcd(unsigned val)
{
	return ((val/10)<<4)+val%10;
}

static unsigned RTC_bcd2bin(unsigned char val)
{
	return (val&0x0f)+(val>>4)*10;
}

/*
Функция: инициализация DS1302
Аппаратное подключение Tiny4412:
	CLK :GPB_4
	DAT :GPB_5
	RST :GPB_6
*/
void DS1302IO_Init(void)
{
	/*1. Зарегистрировать GPIO*/
	gpio_request(EXYNOS4_GPB(4), "DS1302_CLK");
	gpio_request(EXYNOS4_GPB(5), "DS1302_DAT");
	gpio_request(EXYNOS4_GPB(6), "DS1302_RST");
	
	/*2. Настройте режим порта GPIO*/
	s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_OUTPUT);  //часколокол
	s3c_gpio_cfgpin(EXYNOS4_GPB(5), S3C_GPIO_OUTPUT);  //данные
//	s3c_gpio_cfgpin(EXYNOS4_GPB(2), S3C_GPIO_INPUT);   //режим ввода
	s3c_gpio_cfgpin(EXYNOS4_GPB(6), S3C_GPIO_OUTPUT);  //Перезагрузить
	
	/*3. Поднимите порт GPIO*/
	gpio_set_value(EXYNOS4_GPB(4), 1); //CLK
	gpio_set_value(EXYNOS4_GPB(5), 1); //DAT
 	gpio_set_value(EXYNOS4_GPB(6), 1); //RST
	
	gpio_set_value(EXYNOS4_GPB(6), 0);			//Устанавливаем низкий уровень на выводе RST
	gpio_set_value(EXYNOS4_GPB(4), 0);			//Устанавливаем низкий уровень на выводе SCK
}


//#define	RTC_CMD_READ	0x81		/* Read command */
//#define	RTC_CMD_WRITE	0x80		/* Write command */
//#define RTC_ADDR_RAM0	0x20			/* Address of RAM0 */
//#define RTC_ADDR_TCR	0x08			/* Address of trickle charge register */
//#define	RTC_ADDR_YEAR	0x06		/* Address of year register */
//#define	RTC_ADDR_DAY	0x05		/* Address of day of week register */
//#define	RTC_ADDR_MON	0x04		/* Address of month register */
//#define	RTC_ADDR_DATE	0x03		/* Address of day of month register */
//#define	RTC_ADDR_HOUR	0x02		/* Address of hour register */
//#define	RTC_ADDR_MIN	0x01		/* Address of minute register */
//#define	RTC_ADDR_SEC	0x00		/* Address of second register */


//Определение адреса DS1302
#define ds1302_sec_add			0x80		//Второй адрес данных
#define ds1302_min_add			0x82		//адрес точки данных
#define ds1302_hr_add			0x84		//адрес часовданных
#define ds1302_date_add			0x86		//деньдата адреса
#define ds1302_month_add		0x88		//адрес лунных данных
#define ds1302_day_add			0x8a		//адрес недельных данных
#define ds1302_year_add			0x8c		//Адрес данных Бога
#define ds1302_control_add		0x8e		//Адрес управляющих данных
#define ds1302_charger_add		0x90 					 
#define ds1302_clkburst_add		0xbe

//Начальное определение времени
static unsigned char time_buf[8] = {0x20,0x10,0x06,0x01,0x23,0x59,0x55,0x02};//Начальное время: 23:59:55 1 июня 2010 г. Вторник

static unsigned char readtime[14];//текущее время
static unsigned char sec_buf=0;   //Второйкэш
static unsigned char sec_flag=0;  //Второй флаг


//Записываем один байт данных в DS1302
static void ds1302_write_byte(unsigned char addr, unsigned char d) 
{
	unsigned char i;
	gpio_set_value(EXYNOS4_GPB(6), 1);					//Запускаем шину DS1302	
	//Записываем целевой адрес: addr
	addr = addr & 0xFE;   //Младший бит равен нулю, запись, когда бит регистра 0 равен 0, чтение, когда он равен 1
	for(i=0;i<8;i++)
	{
		if(addr&0x01){gpio_set_value(EXYNOS4_GPB(5), 1);}
		else{gpio_set_value(EXYNOS4_GPB(5), 0);}
		gpio_set_value(EXYNOS4_GPB(4), 1);      //генерируем часы
		gpio_set_value(EXYNOS4_GPB(4), 0);
		addr=addr >> 1;
	}
	
	//Запись данных: d
	for(i=0;i<8;i++)
	{
		if(d & 0x01) {gpio_set_value(EXYNOS4_GPB(5), 1);}
		else {gpio_set_value(EXYNOS4_GPB(5), 0);}
		gpio_set_value(EXYNOS4_GPB(4), 1);    //генерируем часы
		gpio_set_value(EXYNOS4_GPB(4), 0);
		d = d >> 1;
	}
	gpio_set_value(EXYNOS4_GPB(6), 0);		//Остановим шину DS1302
}

//Читаем один байт данных из DS1302
static unsigned char ds1302_read_byte(unsigned char addr)
{
	unsigned char i,temp;	
	gpio_set_value(EXYNOS4_GPB(6), 1);//Запускаем шину DS1302
	//Записываем целевой адрес: addr
	addr=addr | 0x01;    //Младший бит высокий, запись, когда бит регистра 0 равен 0, чтение, когда он равен 1
	for(i=0; i<8; i++)
	{
		if(addr & 0x01){gpio_set_value(EXYNOS4_GPB(5), 1);}
		else {gpio_set_value(EXYNOS4_GPB(5), 0);}
		gpio_set_value(EXYNOS4_GPB(4), 1);
		gpio_set_value(EXYNOS4_GPB(4), 0);
		addr=addr >> 1;
	}
			
	s3c_gpio_cfgpin(EXYNOS4_GPB(5), S3C_GPIO_INPUT);   //режим ввода
	//Выходные данные: температура
	for(i=0; i<8; i++)
	{
		temp=temp>>1;
		if(gpio_get_value(EXYNOS4_GPB(5))){temp |= 0x80;}
		else{temp&=0x7F;}
		gpio_set_value(EXYNOS4_GPB(4), 1);
		gpio_set_value(EXYNOS4_GPB(4), 0);
	}
	s3c_gpio_cfgpin(EXYNOS4_GPB(5), S3C_GPIO_OUTPUT);  //режим вывода
	gpio_set_value(EXYNOS4_GPB(6), 0);					//Остановим шину DS1302
	return temp;
}

//Запись данных часов в DS302
static void ds1302_write_time(struct rtc_time *time) 
{
	ds1302_write_byte(ds1302_control_add,0x00);				//Отключаем защиту от записи 
	ds1302_write_byte(ds1302_sec_add,0x80);					//Приостанавливаем часы 
	//ds1302_write_byte(ds1302_charger_add,0xa9);	    	//Капельная зарядка
	/*Установить время RTC*/
	
	//Поскольку год DS1302 можно установить только по двум последним цифрам, вам нужно использовать обычный год минус 2000, чтобы получить фактические две последние цифры.
	ds1302_write_byte(ds1302_year_add,RTC_bin2bcd(time->tm_year-2000));		//Год 
	ds1302_write_byte(ds1302_month_add,RTC_bin2bcd(time->tm_mon));		//луна 
	ds1302_write_byte(ds1302_date_add,RTC_bin2bcd(time->tm_mday));		//день 
	ds1302_write_byte(ds1302_hr_add,RTC_bin2bcd(time->tm_hour));		//час 
	ds1302_write_byte(ds1302_min_add,RTC_bin2bcd(time->tm_min));		//точка
	ds1302_write_byte(ds1302_sec_add,RTC_bin2bcd(time->tm_sec));		//Второй
	//ds1302_write_byte(ds1302_day_add,RTC_bin2bcd(time->tm_wday));		//неделя  time->tm_wdayдень недели
	ds1302_write_byte(ds1302_control_add,0x80);			   //Открываем защиту от записи     
}


static int DS1302_rtc_ioctl(struct device *dev, unsigned int cmd,unsigned long arg)
{
	/*Установить время RTC*/
	struct rtc_time time;
	copy_from_user(&time,(const void __user *)arg,sizeof(struct rtc_time));
	ds1302_write_time(&time);
	return 0;
}


//Эта функция вызывается через команду RTC_RD_TIME ioctl уровня приложения
static int tiny4412_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
	rtc_tm->tm_year=RTC_bcd2bin(ds1302_read_byte(ds1302_year_add))+2000;   //Год 
	rtc_tm->tm_mon=RTC_bcd2bin(ds1302_read_byte(ds1302_month_add));   //луна 
	rtc_tm->tm_mday=RTC_bcd2bin(ds1302_read_byte(ds1302_date_add));   //день 
	rtc_tm->tm_hour=RTC_bcd2bin(ds1302_read_byte(ds1302_hr_add));		//час 
	rtc_tm->tm_min=RTC_bcd2bin(ds1302_read_byte(ds1302_min_add));		//точка 
	rtc_tm->tm_sec=RTC_bcd2bin((ds1302_read_byte(ds1302_sec_add))&0x7f);//Второй,Заблокируйте 7-ю цифру второго,избегайте превышения59
	//time_buf[7]=ds1302_read_byte(ds1302_day_add);		//неделя 
	return 0;
}


//Эта функция вызывается через команду RTC_SET_TIME ioctl уровня приложения
static int tiny4412_rtc_settime(struct device *dev, struct rtc_time *tm)
{
	ds1302_write_time(tm); 
	return 0;	
}


/*Операция с файлом RTC*/
static const struct rtc_class_ops DS1302_rtcops = {
	.ioctl=DS1302_rtc_ioctl,
	.read_time	= tiny4412_rtc_gettime,
	.set_time	= tiny4412_rtc_settime
};


static struct rtc_device *rtc=NULL;
/*Функция, которая успешно выполняется при совпадении устройства — функция исследования ресурса*/
static int drv_probe(struct platform_device *pdev)
{	
	rtc = rtc_device_register("DS1302RTC",&pdev->dev, &DS1302_rtcops,THIS_MODULE);
	if(rtc==NULL)
	printk("Ошибка регистрации драйвера RTC 1\n");
	else
  	{
  		printk("Регистрация драйвера RTC прошла успешно1\n");
  	}
	
	/*1. Инициализировать порт GPIO*/
	DS1302IO_Init();
	msleep(10);	
	return 0;
}


static int drv_remove(struct platform_device *dev)/*Эта функция вызывается при удалении устройства*/
{
	/*Освобождаем порт GPIO*/
	gpio_free(EXYNOS4_GPB(4));
	gpio_free(EXYNOS4_GPB(5));
	gpio_free(EXYNOS4_GPB(6));
	
	rtc_device_unregister(rtc);
	printk("Драйвер RTC успешно удален\n");
	return 0;
}


/*Структура драйвера устройства платформы — содержит имя устройства, соответствующее зонду*/
struct platform_driver  drv= 
{
	.probe = drv_probe,    /*Необходимо создать функцию зонда, которая будет управлять устройством*/
	.remove = drv_remove,  /*Создаем функцию удаления для выхода из устройства*/
	.driver = 
	{
		.name = "DS1302rtc",/*Имя устройства,используется с Сторона устройствоматч (очень важно)*/
	},
};

/*Функция входа драйвера платформы*/
static int __init plat_drv_init(void)
{
	platform_driver_register(&drv);/*зарегистрироватьсяплатформаводить машину*/	
	return 0;
}

/*Функция экспорта драйвера платформы*/
static void __exit plat_drv_exit(void)
{
	platform_driver_unregister(&drv);/*выпускатьплатформаводить машину*/
}

module_init(plat_drv_init);  /*Вход модуля драйвера*/
module_exit(plat_drv_exit);  /*Экспорт модуля драйвера*/
MODULE_LICENSE("GPL");       /*Положение о водительских правах*/

Код стороны устройства DS1320

Язык кода:javascript
копировать
#include "linux/module.h"
#include "linux/init.h"
#include <linux/platform_device.h>
/*
 * device  Сторона устройства
 */

//Освобождаем шину платформы
static void pdev_release(struct device *dev)
{
	printk("rtc_pdev:the rtc_pdev is close!!!\n");
}

/*Сторона устройства Структура*/
struct platform_device  rtc_pdev= /*Структура устройства, имя устройства очень важно!*/
{
	.name = "DS1302rtc",  /*Имя устройства*/
	.id = -1,         /*-1 означает, что имя устройства здесь будет указано после успешного создания. Если значение равно 0 или 1, имя устройства будет myled.0, myled.1...*/.
	.dev =            /*Вызывается при удалении драйвера*/
	{
		.release = pdev_release,/*Освободить ресурсы*/
	},
};


/*платформа Сторона функция входа в устройство*/
static int __init plat_dev_init(void)
{
	platform_device_register(&rtc_pdev);/*зарегистрироватьсяплатформа Сторона устройства*/
	return 0;
}

/*платформа Сторона функция экспорта устройства */
static void __exit plat_dev_exit(void)
{
	platform_device_unregister(&rtc_pdev);/*Выйтиплатформа Сторона устройства*/
}

module_init(plat_dev_init);
module_exit(plat_dev_exit);
MODULE_LICENSE("GPL");
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose