BeRTOS
|
00001 00047 #include "hw/thermo_map.h" 00048 #include "hw/hw_thermo.h" 00049 00050 #include "cfg/cfg_thermo.h" 00051 00052 #include <cfg/module.h> 00053 #include <cfg/macros.h> 00054 #include <cfg/debug.h> 00055 // Define logging setting (for cfg/log.h module). 00056 #define LOG_LEVEL CONFIG_THERMO_LOG_LEVEL 00057 #define LOG_VERBOSITY CONFIG_THERMO_LOG_FORMAT 00058 #include <cfg/log.h> 00059 00060 #include <drv/thermo.h> 00061 #include <drv/timer.h> 00062 #include <drv/ntc.h> 00063 00064 #include <kern/proc.h> 00065 00066 #define THERMO_OFF 0 00067 #define THERMO_HEATING BV(0) 00068 #define THERMO_FREEZING BV(1) 00069 #define THERMO_TGT_REACH BV(2) 00070 #define THERMOERRF_NTCSHORT BV(3) 00071 #define THERMOERRF_NTCOPEN BV(4) 00072 #define THERMOERRF_TIMEOUT BV(5) 00073 #define THERMO_ACTIVE BV(6) 00074 #define THERMO_TIMER BV(7) 00075 00076 #define THERMO_ERRMASK (THERMOERRF_NTCSHORT | THERMOERRF_NTCOPEN | THERMOERRF_TIMEOUT) 00077 00078 00079 #if CONFIG_KERN 00080 00081 static PROC_DEFINE_STACK(thermo_poll_stack, 400); 00082 #else 00083 00084 static Timer thermo_timer; 00085 #endif 00086 00087 typedef struct ThermoControlDev 00088 { 00089 deg_t hifi_samples[CONFIG_THERMO_HIFI_NUM_SAMPLES]; 00090 deg_t cur_hifi_sample; 00091 deg_t target; 00092 thermostatus_t status; 00093 ticks_t expire; 00094 ticks_t on_time; 00095 } ThermoControlDev; 00096 00098 ThermoControlDev devs[THERMO_CNT]; 00099 00103 thermostatus_t thermo_status(ThermoDev dev) 00104 { 00105 ASSERT(dev < THERMO_CNT); 00106 return devs[dev].status; 00107 } 00108 00109 00113 static void thermo_do(ThermoDev index) 00114 { 00115 ThermoControlDev* dev = &devs[index]; 00116 deg_t cur_temp; 00117 deg_t tolerance = thermo_hw_tolerance(index); 00118 00119 cur_temp = thermo_hw_read(index); 00120 00121 // Store the sample into the hifi FIFO buffer for later interpolation 00122 dev->hifi_samples[dev->cur_hifi_sample] = cur_temp; 00123 if (++dev->cur_hifi_sample == CONFIG_THERMO_HIFI_NUM_SAMPLES) 00124 dev->cur_hifi_sample = 0; 00125 00126 cur_temp = thermo_readTemperature(index); 00127 00128 if (cur_temp == NTC_SHORT_CIRCUIT || cur_temp == NTC_OPEN_CIRCUIT) 00129 { 00130 if (cur_temp == NTC_SHORT_CIRCUIT) 00131 { 00132 LOG_INFOB(if (!(dev->status & THERMOERRF_NTCSHORT)) 00133 LOG_INFO("dev[%d], thermo_do: NTC_SHORT\n",index);); 00134 00135 dev->status |= THERMOERRF_NTCSHORT; 00136 } 00137 else 00138 { 00139 00140 LOG_INFOB(if (!(dev->status & THERMOERRF_NTCOPEN)) 00141 LOG_INFO("dev[%d], thermo_do: NTC_OPEN\n", index);); 00142 00143 dev->status |= THERMOERRF_NTCOPEN; 00144 } 00145 00146 /* Reset timeout when there is an ntc error */ 00147 dev->expire = thermo_hw_timeout(index) + timer_clock(); 00148 thermo_hw_off(index); 00149 return; 00150 } 00151 dev->status &= ~(THERMOERRF_NTCOPEN | THERMOERRF_NTCSHORT); 00152 00153 if ((cur_temp < dev->target - tolerance) || (cur_temp > dev->target + tolerance)) 00154 { 00155 dev->status &= ~THERMO_TGT_REACH; 00156 00157 /* Check for timeout */ 00158 if (timer_clock() - dev->expire > 0) 00159 { 00160 dev->status |= THERMOERRF_TIMEOUT; 00161 LOG_INFO("dev[%d], thermo_do: TIMEOUT\n", index); 00162 } 00163 } 00164 else /* In target */ 00165 { 00166 /* Clear errors */ 00167 dev->status &= ~THERMO_ERRMASK; 00168 dev->status |= THERMO_TGT_REACH; 00169 00170 /* Reset timeout in case we go out of target in the future */ 00171 dev->expire = thermo_hw_timeout(index) + timer_clock(); 00172 } 00173 00174 if (cur_temp < dev->target) 00175 dev->status = (dev->status | THERMO_HEATING) & ~THERMO_FREEZING; 00176 else 00177 dev->status = (dev->status & ~THERMO_HEATING) | THERMO_FREEZING; 00178 00179 thermo_hw_set(index, dev->target, cur_temp); 00180 00181 } 00182 00183 static void poll(void) 00184 { 00185 for (int i = 0; i < THERMO_CNT; ++i) 00186 if (devs[i].status & THERMO_ACTIVE) 00187 { 00188 LOG_INFO("THERMO [%d] on_time[%ld],\n", i, ticks_to_ms(devs[i].on_time)); 00189 if ((devs[i].status & THERMO_TIMER) && (devs[i].on_time - timer_clock() < 0)) 00190 { 00191 thermo_stop(i); 00192 continue; 00193 } 00194 00195 thermo_do((ThermoDev)i); 00196 } 00197 } 00198 00199 #if CONFIG_KERN 00200 static void NORETURN thermo_poll(void) 00201 { 00202 for (;;) 00203 { 00204 poll(); 00205 timer_delay(CONFIG_THERMO_INTERVAL_MS); 00206 } 00207 } 00208 #else 00209 00212 static void thermo_softint(void) 00213 { 00214 poll(); 00215 timer_add(&thermo_timer); 00216 } 00217 #endif 00218 00223 void thermo_timer(ThermoDev dev, mtime_t on_time) 00224 { 00225 ASSERT(dev < THERMO_CNT); 00226 devs[dev].on_time = timer_clock() + ms_to_ticks(on_time); 00227 devs[dev].status |= THERMO_TIMER; 00228 thermo_start(dev); 00229 } 00230 00231 00235 void thermo_setTarget(ThermoDev dev, deg_t temperature) 00236 { 00237 ASSERT(dev < THERMO_CNT); 00238 devs[dev].target = temperature; 00239 devs[dev].expire = timer_clock() + thermo_hw_timeout(dev); 00240 00241 LOG_INFO("THERMO Set Target dev[%d], T[%d.%d]\n", dev, temperature / 10, temperature % 10); 00242 } 00243 00247 void thermo_start(ThermoDev dev) 00248 { 00249 int i; 00250 deg_t temp; 00251 00252 ASSERT(dev < THERMO_CNT); 00253 00254 devs[dev].status |= THERMO_ACTIVE; 00255 LOG_INFO("THERMO Start dev[%d], status[%04x]\n", dev, devs[dev].status); 00256 00257 /* Initialize the hifi FIFO with a constant value (the current temperature) */ 00258 temp = thermo_hw_read(dev); 00259 for (i = 0; i < CONFIG_THERMO_HIFI_NUM_SAMPLES; ++i) 00260 devs[dev].hifi_samples[i] = temp; 00261 devs[dev].cur_hifi_sample = 0; 00262 00263 /* Reset timeout */ 00264 devs[dev].expire = timer_clock() + thermo_hw_timeout(dev); 00265 } 00266 00270 void thermo_stop(ThermoDev dev) 00271 { 00272 ASSERT(dev < THERMO_CNT); 00273 00274 devs[dev].status &= ~THERMO_ACTIVE; 00275 thermo_hw_off(dev); 00276 } 00277 00278 00282 void thermo_clearErrors(ThermoDev dev) 00283 { 00284 ASSERT(dev < THERMO_CNT); 00285 devs[dev].status &= ~(THERMO_ERRMASK); 00286 } 00287 00288 00292 deg_t thermo_readTemperature(ThermoDev dev) 00293 { 00294 int i; 00295 long accum = 0; 00296 00297 MOD_CHECK(thermo); 00298 00299 for (i = 0; i < CONFIG_THERMO_HIFI_NUM_SAMPLES; i++) 00300 accum += devs[dev].hifi_samples[i]; 00301 00302 return (deg_t)(accum / CONFIG_THERMO_HIFI_NUM_SAMPLES); 00303 } 00304 00305 MOD_DEFINE(thermo) 00306 00307 00310 void thermo_init(void) 00311 { 00312 THERMO_HW_INIT; 00313 00314 /* Set all status to off */ 00315 for (int i = 0; i < THERMO_CNT; i++) 00316 devs[i].status = THERMO_OFF; 00317 00318 MOD_INIT(thermo); 00319 00320 #if CONFIG_KERN 00321 proc_new_with_name("Thermo", thermo_poll, NULL, sizeof(thermo_poll_stack), thermo_poll_stack); 00322 #else 00323 timer_setDelay(&thermo_timer, ms_to_ticks(CONFIG_THERMO_INTERVAL_MS)); 00324 timer_setSoftint(&thermo_timer, (Hook)thermo_softint, 0); 00325 timer_add(&thermo_timer); 00326 #endif 00327 }