• 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   (Optional) For new drivers, verify the basic functions, such as the RTC status control and response to interrupts.
71
72
73## Development Example
74
75The following uses **rtc_hi35xx.c** as an example to present the information required for implementing device functions.
76
771. Instantiate the driver entry.<br/>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**. In the HDF framework, 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.
78   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.
79
80     RTC driver entry example:
81
82   ```
83   struct HdfDriverEntry g_rtcDriverEntry = {
84     .moduleVersion = 1,
85     .Bind = HiRtcBind,                // See the Bind function.
86     .Init = HiRtcInit,              // See the Init function.
87     .Release = HiRtcRelease,         //See the Release function.
88     .moduleName = "HDF_PLATFORM_RTC", // (Mandatory) The value must be the same as that in the .hcs file.
89   };
90   // Call HDF_INIT to register the driver entry with the HDF.
91   HDF_INIT(g_rtcDriverEntry);
92   ```
93
942. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **rtc_config.hcs** file.
95
96   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.
97   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.
98
99   - **device_info.hcs** configuration example
100
101
102     ```
103     root {
104       device_info {
105         platform :: host {
106           device_rtc :: device {
107             device0 :: deviceNode {
108               policy = 1;                              // The driver publishes services for kernel-mode processes only.
109               priority = 30;                           // A smaller value indicates a higher priority.
110               permission = 0644;                  // Permission for the driver to create a device node
111               moduleName = "HDF_PLATFORM_RTC";         // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
112               serviceName = "HDF_PLATFORM_RTC";         // (Mandatory) Unique name of the service published by the driver.
113               deviceMatchAttr = "hisilicon_hi35xx_rtc";// The value must be the same as that of match_attr in the .hcs file.
114             }
115           }
116         }
117       }
118     }
119     ```
120
121   - **rtc_config.hcs** configuration example
122
123
124     ```
125     root {
126       platform {
127         rtc_config {
128           controller_0x12080000 {
129             match_attr = "hisilicon_hi35xx_rtc";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
130             rtcSpiBaseAddr = 0x12080000;        // Used for address mapping.
131             regAddrLength = 0x100;              // Used for address mapping.
132             irq = 37;                           // Interrupt number.
133             supportAnaCtrl = false;
134             supportLock = false;
135             anaCtrlAddr = 0xff;
136             lock0Addr = 0xff;
137             lock1Addr = 0xff;
138             lock2Addr = 0xff;
139             lock3Addr = 0xff;
140           }
141         }
142       }
143     }
144     ```
145
1463. 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).
147   - Defining a custom structure
148
149      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.
150
151
152      ```
153      struct RtcConfigInfo {
154        uint32_t           spiBaseAddr; // Used for address mapping.
155        volatile void      *remapBaseAddr;  // Used for address mapping.
156        uint16_t           regAddrLength; // Used for address mapping.
157        uint8_t            supportAnaCtrl; // Whether ANACTRL is supported.
158        uint8_t            supportLock;    // Whether lock is supported.
159        uint8_t            irq;            // Interrupt number.
160        uint8_t            alarmIndex;    // RTC alarm index.
161        uint8_t            anaCtrlAddr; // ANACTRL address.
162        struct RtcLockAddr lockAddr;      // Lock address.
163        RtcAlarmCallback   cb;             // Callback.
164        struct OsalMutex   mutex;          // Mutex.
165      };
166
167      // RtcHost is the controller structure at the core layer. The Init function assigns values to the members of RtcHost.
168      struct RtcHost {
169          struct IDeviceIoService service;
170          struct HdfDeviceObject *device;
171          struct RtcMethod *method;
172          void *data;
173      };
174      ```
175   - Instantiating **RtcMethod** in **RtcHost** (other members are initialized by **Init**)
176
177
178      ```
179      // Example in rtc_hi35xx.c: instantiate the hook.
180      static struct RtcMethod g_method = {
181          .ReadTime   = HiRtcReadTime,
182          .WriteTime  = HiRtcWriteTime,
183          .ReadAlarm  = HiReadAlarm,
184          .WriteAlarm = HiWriteAlarm,
185          .RegisterAlarmCallback  = HiRegisterAlarmCallback,
186          .AlarmInterruptEnable   = HiAlarmInterruptEnable,
187          .GetFreq  = HiGetFreq,
188          .SetFreq  = HiSetFreq,
189          .Reset       = HiReset,
190          .ReadReg  = HiReadReg,
191          .WriteReg = HiWriteReg,
192      };
193      ```
194
195   - **Bind** function
196
197      Input parameter:
198
199      **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
200
201      Return value:
202
203      HDF_STATUS<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
204
205        **Table 2** HDF_STATUS
206
207      | Status| Description|
208      | -------- | -------- |
209      | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
210      | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
211      | HDF_ERR_INVALID_PARAM | Invalid parameter.|
212      | HDF_ERR_IO | I/O error.|
213      | HDF_SUCCESS | Initialization successful.|
214      | HDF_FAILURE | Initialization failed.|
215
216      Function description:
217
218      Binds the **HdfDeviceObject** object and **RtcHost**.
219
220
221      ```
222      static int32_t HiRtcBind(struct HdfDeviceObject *device)
223      {
224        struct RtcHost *host = NULL;
225        host = RtcHostCreate(device); // Allocate memory and attach the device host and the device.
226                                         // Prerequisite for conversion between HdfDeviceObject and RtcHost.
227        ...
228        device->service = &host->service; // Prerequisite for conversion between HdfDeviceObject and RtcHost.
229                                         // It helps implement the global host by calling RtcHostFromDevice.
230        return HDF_SUCCESS;
231      }
232      ```
233
234   - **Init** function
235
236      Input parameter:
237
238      **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
239
240      Return value:
241
242      HDF_STATUS
243
244      Function description:
245
246      Initializes the custom structure object and **RtcHost**.
247
248
249      ```
250      static int32_t HiRtcInit(struct HdfDeviceObject *device)
251      {
252        struct RtcHost *host = NULL;
253        struct RtcConfigInfo *rtcInfo = NULL;
254        ...
255        host = RtcHostFromDevice(device);// Forcibly convert HdfDeviceObject to RtcHost.
256        rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
257        ...
258        // HiRtcConfigData reads attributes from the device configuration tree and fills the values in supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength, and irq in rtcInfo.
259        // Provide parameters for HiRtcSwInit and HiRtcSwInit. When HiRtcSwInit and HiRtcSwInit fail to be executed internally, operations such as memory release can be performed.
260        if (HiRtcConfigData(rtcInfo, device->property) != 0) {
261          ...
262        }
263        if (HiRtcSwInit(rtcInfo)! = 0) {// Address mapping and interrupt registration.
264          ...
265        }
266        if (HiRtcHwInit(rtcInfo)! = 0) {// Initialize ANACTRL and lockAddr.
267          ...
268        }
269
270        host->method = &g_method; // Attach the RtcMethod instance.
271        host->data = rtcInfo; // Prerequisites for conversion between RtcConfigInfo and RtcHost.
272        HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
273        return HDF_SUCCESS;
274      }
275      ```
276   - **Release** function
277
278      Input parameter:
279
280      **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
281
282      Return value:
283
284      No value is returned.
285
286      Function description:
287
288      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. 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.
289
290
291      ```
292      static void HiRtcRelease(struct HdfDeviceObject *device)
293      {
294          struct RtcHost *host = NULL;
295          struct RtcConfigInfo *rtcInfo = NULL;
296          ...
297          host = RtcHostFromDevice(device);            // Forcibly convert HdfDeviceObject to RtcHost.
298          rtcInfo = (struct RtcConfigInfo *)host->data;// Forcibly convert RtcHost to RtcConfigInfo.
299          if (rtcInfo != NULL) {
300              HiRtcSwExit(rtcInfo);
301              OsalMemFree(rtcInfo);                    // Release RtcConfigInfo.
302              host->data = NULL;
303          }
304          RtcHostDestroy(host);                        // Release RtcHost.
305      }
306      ```
307