/* * 第3回 TOPPERS活用アイデア・アプリケーション開発コンテスト * 松浦 光洋さんの「lwIP の移植」をベースにしました。 * http://www.toppers.jp/contest.html * * @(#) $Id: sys_arch.c 167 2016-03-08 11:37:45Z coas-nagasima $ */ #include #include #include #include "arch/sys_arch.h" #include "lwip/opt.h" #include "lwip/debug.h" #include "lwip/def.h" #include "lwip/sys.h" #include "lwip/mem.h" #include "lwip/stats.h" #include "tlsf.h" static tlsf_t lwip_tlsf; static pool_t lwip_pool; extern void *lwip_heap; extern size_t lwip_heapsz; extern ID _echonet_ecn_mem_semid; void syslog_info(const char *format, ...) { va_list ap; va_start(ap, format); vsyslog(LOG_NOTICE, format, ap); va_end(ap); } void syslog_assert(const char *format, ...) { va_list ap; va_start(ap, format); vsyslog(LOG_EMERG, format, ap); va_end(ap); } void sys_init(void) { lwip_tlsf = tlsf_create(lwip_heap); if (lwip_tlsf == NULL) return; lwip_pool = tlsf_add_pool(lwip_tlsf, ((uint8_t *)lwip_heap) + tlsf_size(), lwip_heapsz - tlsf_size()); } err_t sys_sem_new(sys_sem_t *sem, u8_t count) { err_t ret = ERR_VAL; syslog(LOG_DEBUG, "sys_sem_new in\n"); if (NULL != sem) { T_CSEM csem = { TA_TPRI, (uint_t)count, (uint_t)1 }; ID id = acre_sem(&csem); if (0 < id) { *sem = id; ret = ERR_OK; syslog(LOG_DEBUG, "sys_sem_new out %d, %d\n", *sem, count); } else { *sem = (sys_sem_t)NULL; syslog(LOG_DEBUG, "sys_sem_new out ERROR!\n"); } } return ret; } void sys_sem_free(sys_sem_t *sem) { syslog(LOG_DEBUG, "sys_sem_free in %d\n", *sem); del_sem(*sem); *sem = (sys_sem_t)NULL; syslog(LOG_DEBUG, "sys_sem_free out\n"); return; } void sys_sem_signal(sys_sem_t *sem) { syslog(LOG_DEBUG, "sys_sem_signal in %d\n", *sem); sig_sem(*sem); syslog(LOG_DEBUG, "sys_sem_signal out %d\n", *sem); return; } u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { SYSTIM systim0, systim1; ER ercd; get_tim(&systim0); syslog(LOG_DEBUG, "sys_arch_sem_wait in %d\n", *sem); if (timeout) { ercd = twai_sem(*sem, (TMO)timeout); } else { ercd = wai_sem(*sem); } if (E_OK == ercd) { get_tim(&systim1); syslog(LOG_DEBUG, "sys_arch_sem_wait out %d, E_OK\n", *sem); return (u32_t)(systim1 - systim0); } syslog(LOG_DEBUG, "sys_arch_sem_wait out %d, SYS_ARCH_TIMEOUT\n", *sem); return SYS_ARCH_TIMEOUT; } err_t sys_mbox_new(sys_mbox_t *mbox, int size) { err_t ret = ERR_VAL; syslog(LOG_DEBUG, "sys_mbox_new in\n"); if (NULL != mbox) { T_CDTQ cdtq = { TA_NULL, (uint_t)size, (void *)NULL }; ID id = acre_dtq(&cdtq); if (0 < id) { *mbox = id; ret = ERR_OK; syslog(LOG_DEBUG, "sys_mbox_new out %d, %d\n", *mbox, size); } else { *mbox = (sys_mbox_t)NULL; syslog(LOG_DEBUG, "sys_mbox_new out ERROR!\n"); } } return ret; } void sys_mbox_free(sys_mbox_t *mbox) { syslog(LOG_DEBUG, "sys_mbox_free in %d\n", *mbox); del_dtq(*mbox); *mbox = (sys_mbox_t)NULL; syslog(LOG_DEBUG, "sys_mbox_free out\n"); return; } void sys_mbox_post(sys_mbox_t *mbox, void *msg) { syslog(LOG_DEBUG, "sys_mbox_post in %d, 0x%08x\n", *mbox, msg); snd_dtq(*mbox, (intptr_t)msg); syslog(LOG_DEBUG, "sys_mbox_post out %d, 0x%08x\n", *mbox, msg); return; } err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { err_t ret = ERR_VAL; syslog(LOG_DEBUG, "sys_mbox_trypost in %d, 0x%08x\n", *mbox, msg); if (E_OK == psnd_dtq(*mbox, (intptr_t)msg)) { ret = ERR_OK; } syslog(LOG_DEBUG, "sys_mbox_trypost out %d, 0x%08x %d\n", *mbox, msg, ret); return ret; } u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) { SYSTIM systim0, systim1; ER ercd; get_tim(&systim0); syslog(LOG_DEBUG, "sys_arch_mbox_fetch in %d\n", *mbox); if (timeout) { ercd = trcv_dtq(*mbox, (intptr_t *)msg, timeout); } else { ercd = rcv_dtq(*mbox, (intptr_t*)msg); } if (E_OK == ercd) { get_tim(&systim1); syslog(LOG_DEBUG, "sys_arch_mbox_fetch out %d, E_OK\n", *mbox); return (u32_t)(systim1 - systim0); } syslog(LOG_DEBUG, "sys_arch_mbox_fetch out %d, SYS_ARCH_TIMEOUT\n", *mbox); return SYS_ARCH_TIMEOUT; } u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { syslog(LOG_DEBUG, "sys_arch_mbox_tryfetch in %d\n", *mbox); if (E_OK == prcv_dtq(*mbox, (intptr_t *)msg)) { syslog(LOG_DEBUG, "sys_arch_mbox_tryfetch out %d, 0x%08x, ERR_OK\n", *mbox, *msg); return (u32_t)ERR_OK; } syslog(LOG_DEBUG, "sys_arch_mbox_tryfetch out %d, SYS_MBOX_EMPTY\n", *mbox); return SYS_MBOX_EMPTY; } sys_thread_t sys_thread_new(const char *name, void(*thread)(void *), void *arg, int stacksize, int prio) { syslog(LOG_DEBUG, "sys_thread_new in\n"); T_CTSK ctsk = { TA_ACT, (intptr_t)arg, (TASK)thread, (PRI)prio, (SIZE)stacksize, (STK_T *)NULL }; ID id = acre_tsk(&ctsk); syslog(LOG_DEBUG, "sys_thread_new %s, %d, %d, %d\n", name, stacksize, prio, id); return (sys_thread_t)id; } sys_prot_t sys_arch_protect(void) { bool_t state = sns_loc(); if (!state) { loc_cpu(); } return (sys_prot_t)(~state); } void sys_arch_unprotect(sys_prot_t pval) { if (pval) { unl_cpu(); } return; } u32_t sys_now(void) { SYSTIM systim; get_tim(&systim); return (u32_t)systim; } void *sys_malloc(size_t size) { ER ret; void *p; ret = wai_sem(_echonet_ecn_mem_semid); p = tlsf_malloc(lwip_tlsf, size); if (ret == E_OK) sig_sem(_echonet_ecn_mem_semid); if (p == NULL) { syslog(LOG_ERROR, "tlsf_malloc %d", size); } return p; } void *sys_calloc(size_t count, size_t size) { ER ret; void *p; ret = wai_sem(_echonet_ecn_mem_semid); p = tlsf_malloc(lwip_tlsf, count * size); if (ret == E_OK) sig_sem(_echonet_ecn_mem_semid); if (p != NULL) { memset(p, 0, count * size); } else { syslog(LOG_ERROR, "tlsf_malloc %d", size); } return p; } void *sys_realloc(void *ptr, size_t size) { ER ret; void *p; ret = wai_sem(_echonet_ecn_mem_semid); p = tlsf_realloc(lwip_tlsf, ptr, size); if (ret == E_OK) sig_sem(_echonet_ecn_mem_semid); if (p == NULL) { syslog(LOG_ERROR, "tlsf_realloc %d", size); } return p; } void sys_free(void *mem) { ER ret; ret = wai_sem(_echonet_ecn_mem_semid); tlsf_free(lwip_tlsf, mem); if (ret == E_OK) sig_sem(_echonet_ecn_mem_semid); } void *sys_trim(void *mem, size_t size) { return mem; } void sys_sleep(uint32_t ms) { dly_tsk(ms); } void sys_sprintf(void *dst, const char *fmt, ...) { va_list arp; unsigned int r, i, j, w, f; unsigned long v; char s[16], c, d, *p; char *pos = (char *)dst; va_start(arp, fmt); for (;;) { c = *fmt++; /* Get a char */ if (!c) break; /* End of format? */ if (c != '%') { /* Pass through it if not a % sequense */ *pos++ = c; continue; } f = 0; c = *fmt++; /* Get first char of the sequense */ if (c == '0') { /* Flag: '0' padded */ f = 1; c = *fmt++; } else { if (c == '-') { /* Flag: left justified */ f = 2; c = *fmt++; } } for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */ w = w * 10 + c - '0'; if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ f |= 4; c = *fmt++; } if (!c) break; /* End of format? */ d = c; if (d >= 'a') d -= 0x20; switch (d) { /* Type is... */ case 'S': /* String */ p = va_arg(arp, char*); for (j = 0; p[j]; j++); while (!(f & 2) && j++ < w) *pos++ = ' '; while (*p != '\0') *pos++ = *p++; while (j++ < w) *pos++ = ' '; continue; case 'C': /* Character */ *pos++ = (char)va_arg(arp, int); continue; case 'B': /* Binary */ r = 2; break; case 'O': /* Octal */ r = 8; break; case 'D': /* Signed decimal */ case 'U': /* Unsigned decimal */ r = 10; break; case 'X': /* Hexdecimal */ r = 16; break; default: /* Unknown type (passthrough) */ *pos++ = c; continue; } /* Get an argument and put it in numeral */ v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int)); if (d == 'D' && (v & 0x80000000)) { v = 0 - v; f |= 8; } i = 0; do { d = (char)(v % r); v /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; } while (v && i < sizeof(s)); if (f & 8) s[i++] = '-'; j = i; d = (f & 1) ? '0' : ' '; while (!(f & 2) && j++ < w) *pos++ = d; do *pos++ = s[--i]; while (i); while (j++ < w) *pos++ = ' '; } va_end(arp); } FIL fil[3]; #define fil_count (sizeof(fil) / sizeof(fil[0])) FIL *sys_fopen(const char *file, const char *mode) { FIL *result = NULL; int i; for (i = 0; i < fil_count; i++) { if (fil[i].fs == NULL) { result = &fil[i]; break; } } if (result == NULL) return NULL; if (f_open(result, file, mode[0] == 'r' ? FA_READ : FA_WRITE) != FR_OK) { return NULL; } return result; } size_t sys_fread(void *data, size_t len, size_t size, FIL *fp) { UINT result; switch ((intptr_t)fp) { case 1: case 2: case 3: return 0; default: if (f_read(fp, data, len * size, &result) != FR_OK) { return 0; } break; } return result; } size_t sys_fwrite(const void *data, size_t len, size_t size, FIL *fp) { UINT result; switch ((intptr_t)fp) { case 1: syslog(LOG_ERROR, data); return len * size; case 2: syslog(LOG_NOTICE, data); return len * size; case 3: return 0; default: if (f_write(fp, data, len * size, &result) != FR_OK) { return 0; } break; } return result; } long sys_fseek(FIL *fp, long ofs, long mode) { FRESULT res; switch (mode) { case SEEK_SET: res = f_lseek((fp), ofs); break; case SEEK_CUR: res = f_lseek((fp), (fp)->fptr + ofs); break; case SEEK_END: res = f_lseek((fp), (fp)->fsize - ofs); break; default: return -1; } return (res == FR_OK) ? 0 : -1; } long sys_fclose(FIL *fp) { if (f_close(fp) != FR_OK) return EOF; return 0; } char *sys_fgets(char *buf, long len, FIL *fp) { return f_gets(buf, len, fp); } long sys_fputc(long data, FIL *fp) { switch ((intptr_t)fp) { case 1: syslog(LOG_ERROR, "%c", data); return 0; case 2: syslog(LOG_NOTICE, "%c", data); return 0; case 3: return -1; default: return f_putc(data, fp); } } long sys_fputs(const char *data, FIL *fp) { switch ((intptr_t)fp) { case 1: syslog(LOG_ERROR, data); return 0; case 2: syslog(LOG_NOTICE, data); return 0; case 3: return -1; default: return f_puts(data, fp); } } long sys_fflush(FIL *fp) { return 0; } long sys_lseek(FIL *fp, long offset, int origin) { if (f_lseek(fp, offset) != FR_OK) { return -1; } return 0; } long sys_ftell(FIL *fp) { return f_tell(fp); } long sys_ferror(FIL *fp) { return fp->err; } long sys_rewind(FIL *fp) { if (f_lseek(fp, 0) != FR_OK) { return -1; } return 0; } void sys_exit(int error) { abort(); }