• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# RTC
2
3
4## Overview
5
6The real-time clock (RTC) is a real-time clock device in the operating system. In the Hardware Driver Foundation (HDF), the RTC uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage.
7
8  **Figure 1** Independent service mode
9
10  ![image](figures/independent-service-mode.png "RTC independent service mode")
11
12
13## Available APIs
14
15**RtcMethod**:
16
17
18```
19struct RtcMethod {
20    int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time);
21    int32_t (*WriteTime)(struct RtcHost *host, const struct RtcTime *time);
22    int32_t (*ReadAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *time);
23    int32_t (*WriteAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *time);
24    int32_t (*RegisterAlarmCallback)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb);
25    int32_t (*AlarmInterruptEnable)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable);
26    int32_t (*GetFreq)(struct RtcHost *host, uint32_t *freq);
27    int32_t (*SetFreq)(struct RtcHost *host, uint32_t freq);
28    int32_t (*Reset)(struct RtcHost *host);
29    int32_t (*ReadReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t *value);
30    int32_t (*WriteReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t value);
31};
32```
33
34  **Table 1** Description of the callback functions in RtcMethod
35
36| Function| Input Parameter| Output Parameter| Return Value| Description|
37| -------- | -------- | -------- | -------- | -------- |
38| ReadTime | **host**: structure pointer to the RTC controller at the core layer.| **time**: structure pointer to the time read.| HDF_STATUS| Reads the RTC time.|
39| WriteTime | **host**: structure pointer to the RTC controller at the core layer.<br>**time**: structure pointer to the time to write.| –| HDF_STATUS| Writes the RTC time (including the year, month, day, day of week, hour, minute, second, and millisecond).|
40| ReadAlarm | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.| **time**: structure pointer to the time read.| HDF_STATUS| Reads the RTC alarm time.|
41| WriteAlarm | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**time**: structure pointer to the time to write.| –| HDF_STATUS| Writes the RTC alarm time.|
42| RegisterAlarmCallback | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**cb**: pointer to the callback to register.| –| HDF_STATUS| Registers a callback to be invoked when an alarm is not generated at the specified time.|
43| AlarmInterruptEnable | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**enable**: whether to enable interrupts for an RTC alarm. | –| HDF_STATUS| Enables or disables interrupts for an RTC alarm.|
44| GetFreq | **host**: structure pointer to the RTC controller at the core layer.| **freq**: pointer to the frequency obtained, which is of the uint32_t type.| HDF_STATUS| Obtains the frequency of the external crystal oscillator connected to the RTC driver.|
45| SetFreq | **host**: structure pointer to the RTC controller at the core layer.<br>**freq**: frequency to set, which is of the uint32_t type.| –| HDF_STATUS| Sets the frequency of the external crystal oscillator connected to the RTC driver.|
46| Reset | **host**: structure pointer to the RTC controller at the core layer.| –| HDF_STATUS| Resets the RTC.|
47| ReadReg | **host**: structure pointer to the RTC controller at the core layer.<br>**usrDefIndex**: index of a custom register.| **value**: pointer to the register value obtained, which is of the uint8_t type.| HDF_STATUS| Reads a custom RTC register. A register index corresponds to one byte of the register value.|
48| WriteReg | **host**: structure pointer to the RTC controller at the core layer.<br>**usrDefIndex**: index of a custom register.<br>**value**: register value to write, which is of the uint8_t type.| –| HDF_STATUS| Writes a custom RTC register. A register index corresponds to one byte of the register value.|
49
50
51## How to Develop
52
53The RTC module adaptation involves the following steps:
54
551. Instantiate the driver entry.
56   - Instantiate the **HdfDriverEntry** structure.
57   - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
58
592. Configure attribute files.
60   - Add the **deviceNode** information to the **device_info.hcs** file.
61   - (Optional) Add the **rtc_config.hcs** file.
62
633. Instantiate the RTC controller object.
64   - Initialize **RtcHost**.
65   - Instantiate **RtcMethod** in the **RtcHost** object.
66      > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
67      > For details about the functions in **RtcMethod**, see [Available APIs](#available-apis).
68
694. Debug the driver.
70
71   (Optional) For new drivers, verify the basic functions, such as the RTC status control and response to interrupts.
72
73
74## Development Example
75
76The following uses **rtc_hi35xx.c** as an example to present the information required for implementing device functions.
77
781. Instantiate the driver entry.
79
80   The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**.
81
82   In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
83
84   Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
85
86   RTC driver entry example:
87
88   ```
89   struct HdfDriverEntry g_rtcDriverEntry = {
90     .moduleVersion = 1,
91     .Bind = HiRtcBind,                // See the Bind function.
92     .Init = HiRtcInit,                // See the Init function.
93     .Release = HiRtcRelease,          //See the Release function.
94     .moduleName = "HDF_PLATFORM_RTC", // (Mandatory) The value must be the same as that in the .hcs file.
95   };
96   // Call HDF_INIT to register the driver entry with the HDF.
97   HDF_INIT(g_rtcDriverEntry);
98   ```
99
1002. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **rtc_config.hcs** file.
101
102   The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **RtcHost** members at the core layer.
103
104   In this example, there is only one RTC controller. If there are multiple RTC controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **rtc_config** file for each controller.
105
106   - **device_info.hcs** configuration example
107
108
109     ```
110     root {
111       device_info {
112         platform :: host {
113           device_rtc :: device {
114             device0 :: deviceNode {
115               policy = 1;                              // The driver publishes services for kernel-mode processes only.
116               priority = 30;                           // A smaller value indicates a higher priority.
117               permission = 0644;                       // Permission for the driver to create a device node
118               moduleName = "HDF_PLATFORM_RTC";         // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
119               serviceName = "HDF_PLATFORM_RTC";        // (Mandatory) Unique name of the service published by the driver.
120               deviceMatchAttr = "hisilicon_hi35xx_rtc";// The value must be the same as that of match_attr in the .hcs file.
121             }
122           }
123         }
124       }
125     }
126     ```
127
128   - **rtc_config.hcs** configuration example
129
130
131     ```
132     root {
133       platform {
134         rtc_config {
135           controller_0x12080000 {
136             match_attr = "hisilicon_hi35xx_rtc";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
137             rtcSpiBaseAddr = 0x12080000;        // Used for address mapping.
138             regAddrLength = 0x100;              // Used for address mapping.
139             irq = 37;                           // Interrupt number.
140             supportAnaCtrl = false;
141             supportLock = false;
142             anaCtrlAddr = 0xff;
143             lock0Addr = 0xff;
144             lock1Addr = 0xff;
145             lock2Addr = 0xff;
146             lock3Addr = 0xff;
147           }
148         }
149       }
150     }
151     ```
152
1533. Initialize the **RtcHost** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) to instantiate **RtcMethod** in **RtcHost** (so that the underlying driver functions can be called).
154
155   - Defining a custom structure
156
157      To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **rtc_config.hcs** file to initialize the members in the custom structure.
158
159      ```
160      struct RtcConfigInfo {
161        uint32_t           spiBaseAddr;     // Used for address mapping.
162        volatile void      *remapBaseAddr;  // Used for address mapping.
163        uint16_t           regAddrLength;   // Used for address mapping.
164        uint8_t            supportAnaCtrl;  // Whether ANACTRL is supported.
165        uint8_t            supportLock;     // Whether lock is supported.
166        uint8_t            irq;             // Interrupt number.
167        uint8_t            alarmIndex;      // RTC alarm index.
168        uint8_t            anaCtrlAddr;     // ANACTRL address.
169        struct RtcLockAddr lockAddr;        // Lock address.
170        RtcAlarmCallback   cb;              // Callback.
171        struct OsalMutex   mutex;           // Mutex.
172      };
173
174      // RtcHost is the controller structure at the core layer. The Init function assigns values to the members of RtcHost.
175      struct RtcHost {
176          struct IDeviceIoService service;
177          struct HdfDeviceObject *device;
178          struct RtcMethod *method;
179          void *data;
180      };
181      ```
182
183   - Instantiating **RtcMethod** in **RtcHost** (other members are initialized by **Init**)
184
185      ```
186       // Example in rtc_hi35xx.c: instantiate the hook.
187       static struct RtcMethod g_method = {
188      .ReadTime   = HiRtcReadTime,
189      .WriteTime  = HiRtcWriteTime,
190      .ReadAlarm  = HiReadAlarm,
191      .WriteAlarm = HiWriteAlarm,
192      .RegisterAlarmCallback  = HiRegisterAlarmCallback,
193      .AlarmInterruptEnable   = HiAlarmInterruptEnable,
194      .GetFreq  = HiGetFreq,
195      .SetFreq  = HiSetFreq,
196      .Reset       = HiReset,
197      .ReadReg  = HiReadReg,
198      .WriteReg = HiWriteReg,
199       };
200      ```
201
202   - **Bind** function
203
204     **Input parameter**:
205
206     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
207
208     **Return value**:
209
210     **HDF_STATUS**
211
212     The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
213
214      **Table 2** Description of HDF_STATUS
215
216     | Status                 | Description                |
217     | ---------------------- | -------------------------- |
218     | HDF_ERR_INVALID_OBJECT | Invalid controller object. |
219     | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory. |
220     | HDF_ERR_INVALID_PARAM  | Invalid parameter.         |
221     | HDF_ERR_IO             | I/O error.                 |
222     | HDF_SUCCESS            | Initialization successful. |
223     | HDF_FAILURE            | Initialization failed.     |
224
225     **Function description**:
226
227      Binds the **HdfDeviceObject** object and **RtcHost**.
228
229     ```
230     static int32_t HiRtcBind(struct HdfDeviceObject *device)
231        {
232          struct RtcHost *host = NULL;
233          host = RtcHostCreate(device);    // Allocate memory and attach the device host with the device.
234                                           // Prerequisite for conversion between HdfDeviceObject and RtcHost.
235          ...
236          device->service = &host->service; // Prerequisite for conversion between HdfDeviceObject and RtcHost.
237                                           // It helps implement a global host by calling RtcHostFromDevice.
238       return HDF_SUCCESS;
239        }
240     ```
241
242   - **Init** function
243
244     **Input parameter**:
245
246     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
247
248     **Return value**:
249
250     **HDF_STATUS**
251
252      **Function description**:
253
254     Initializes the custom structure object and **RtcHost**.
255
256     ```
257     static int32_t HiRtcInit(struct HdfDeviceObject *device)
258         {
259           struct RtcHost *host = NULL;
260           struct RtcConfigInfo *rtcInfo = NULL;
261           ...
262           host = RtcHostFromDevice(device);// Forcibly convert HdfDeviceObject to RtcHost.
263           rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
264           ...
265           // HiRtcConfigData reads attributes from the device configuration tree and fills in supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength and irq of RTCInfo.
266           // Provide parameters for HiRtcSwInit and HiRtcSwInit. When HiRtcSwInit and HiRtcSwInit fail to be executed internally, Release() can be called to release memory.
267           if (HiRtcConfigData(rtcInfo, device->property) != 0) {
268             ...
269           }
270           if (HiRtcSwInit(rtcInfo)! = 0) {// Address mapping and interrupt registration.
271             ...
272           }
273           if (HiRtcHwInit(rtcInfo)! = 0) {// Initialize ANACTRL and lockAddr.
274             ...
275           }
276
277           host->method = &g_method; // Attach the RtcMethod instance.
278           host->data = rtcInfo;     // Prerequisites for conversion between RtcConfigInfo and RtcHost.
279           HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
280           return HDF_SUCCESS;
281		 }
282     ```
283
284   - **Release** function
285
286     **Input parameter**:
287
288     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
289
290     **Return value**:
291
292     No value is returned.
293
294     **Function description**:
295
296     Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
297
298
299     > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
300	 > All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** or **Bind** function has the corresponding value assignment operations.
301
302
303     ```
304     static void HiRtcRelease(struct HdfDeviceObject *device)
305         {
306          struct RtcHost *host = NULL;
307          struct RtcConfigInfo *rtcInfo = NULL;
308          ...
309          host = RtcHostFromDevice(device);            // Forcibly convert HdfDeviceObject to RtcHost.
310          rtcInfo = (struct RtcConfigInfo *)host->data;// Forcibly convert RtcHost to RtcConfigInfo.
311          if (rtcInfo != NULL) {
312              HiRtcSwExit(rtcInfo);
313              OsalMemFree(rtcInfo);                    // Release RtcConfigInfo.
314              host->data = NULL;
315          }
316          RtcHostDestroy(host);                        // Release RtcHost.
317         }
318     ```
319