Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2017 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16 #include "mbed.h"
kadonotakashi 0:8fdf9a60065b 17 #include "greentea-client/test_env.h"
kadonotakashi 0:8fdf9a60065b 18 #include "unity.h"
kadonotakashi 0:8fdf9a60065b 19 #include "utest.h"
kadonotakashi 0:8fdf9a60065b 20 #include "rtos.h"
kadonotakashi 0:8fdf9a60065b 21
kadonotakashi 0:8fdf9a60065b 22 #if defined(MBED_RTOS_SINGLE_THREAD)
kadonotakashi 0:8fdf9a60065b 23 #error [NOT_SUPPORTED] test not supported
kadonotakashi 0:8fdf9a60065b 24 #endif
kadonotakashi 0:8fdf9a60065b 25
kadonotakashi 0:8fdf9a60065b 26 #if !DEVICE_USTICKER
kadonotakashi 0:8fdf9a60065b 27 #error [NOT_SUPPORTED] test not supported
kadonotakashi 0:8fdf9a60065b 28 #endif
kadonotakashi 0:8fdf9a60065b 29
kadonotakashi 0:8fdf9a60065b 30 using namespace utest::v1;
kadonotakashi 0:8fdf9a60065b 31
kadonotakashi 0:8fdf9a60065b 32 #if defined(__CORTEX_M23) || defined(__CORTEX_M33)
kadonotakashi 0:8fdf9a60065b 33 #define TEST_STACK_SIZE 768
kadonotakashi 0:8fdf9a60065b 34 #else
kadonotakashi 0:8fdf9a60065b 35 #define TEST_STACK_SIZE 512
kadonotakashi 0:8fdf9a60065b 36 #endif
kadonotakashi 0:8fdf9a60065b 37
kadonotakashi 0:8fdf9a60065b 38 #define TEST_LONG_DELAY 20
kadonotakashi 0:8fdf9a60065b 39 #define TEST_DELAY 10
kadonotakashi 0:8fdf9a60065b 40 #define SIGNALS_TO_EMIT 100
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 Mutex stdio_mutex;
kadonotakashi 0:8fdf9a60065b 43
kadonotakashi 0:8fdf9a60065b 44 volatile int change_counter = 0;
kadonotakashi 0:8fdf9a60065b 45 volatile bool changing_counter = false;
kadonotakashi 0:8fdf9a60065b 46 volatile bool mutex_defect = false;
kadonotakashi 0:8fdf9a60065b 47
kadonotakashi 0:8fdf9a60065b 48 bool manipulate_protected_zone(const int thread_delay)
kadonotakashi 0:8fdf9a60065b 49 {
kadonotakashi 0:8fdf9a60065b 50 bool result = true;
kadonotakashi 0:8fdf9a60065b 51 osStatus stat;
kadonotakashi 0:8fdf9a60065b 52
kadonotakashi 0:8fdf9a60065b 53 stdio_mutex.lock();
kadonotakashi 0:8fdf9a60065b 54
kadonotakashi 0:8fdf9a60065b 55 core_util_critical_section_enter();
kadonotakashi 0:8fdf9a60065b 56 if (changing_counter == true) {
kadonotakashi 0:8fdf9a60065b 57 result = false;
kadonotakashi 0:8fdf9a60065b 58 mutex_defect = true;
kadonotakashi 0:8fdf9a60065b 59 }
kadonotakashi 0:8fdf9a60065b 60 changing_counter = true;
kadonotakashi 0:8fdf9a60065b 61
kadonotakashi 0:8fdf9a60065b 62 change_counter++;
kadonotakashi 0:8fdf9a60065b 63 core_util_critical_section_exit();
kadonotakashi 0:8fdf9a60065b 64
kadonotakashi 0:8fdf9a60065b 65 Thread::wait(thread_delay);
kadonotakashi 0:8fdf9a60065b 66
kadonotakashi 0:8fdf9a60065b 67 core_util_critical_section_enter();
kadonotakashi 0:8fdf9a60065b 68 changing_counter = false;
kadonotakashi 0:8fdf9a60065b 69 core_util_critical_section_exit();
kadonotakashi 0:8fdf9a60065b 70
kadonotakashi 0:8fdf9a60065b 71 stdio_mutex.unlock();
kadonotakashi 0:8fdf9a60065b 72
kadonotakashi 0:8fdf9a60065b 73 return result;
kadonotakashi 0:8fdf9a60065b 74 }
kadonotakashi 0:8fdf9a60065b 75
kadonotakashi 0:8fdf9a60065b 76 void test_thread(int const *thread_delay)
kadonotakashi 0:8fdf9a60065b 77 {
kadonotakashi 0:8fdf9a60065b 78 while (true) {
kadonotakashi 0:8fdf9a60065b 79 manipulate_protected_zone(*thread_delay);
kadonotakashi 0:8fdf9a60065b 80 }
kadonotakashi 0:8fdf9a60065b 81 }
kadonotakashi 0:8fdf9a60065b 82
kadonotakashi 0:8fdf9a60065b 83 /** Test multiple thread
kadonotakashi 0:8fdf9a60065b 84
kadonotakashi 0:8fdf9a60065b 85 Given 3 threads started with different delays and a section protected with a mutex
kadonotakashi 0:8fdf9a60065b 86 when each thread runs it tries to lock the mutex
kadonotakashi 0:8fdf9a60065b 87 then no more than one thread should be able to access protected region
kadonotakashi 0:8fdf9a60065b 88 */
kadonotakashi 0:8fdf9a60065b 89 void test_multiple_threads(void)
kadonotakashi 0:8fdf9a60065b 90 {
kadonotakashi 0:8fdf9a60065b 91 const int t1_delay = TEST_DELAY * 1;
kadonotakashi 0:8fdf9a60065b 92 const int t2_delay = TEST_DELAY * 2;
kadonotakashi 0:8fdf9a60065b 93 const int t3_delay = TEST_DELAY * 3;
kadonotakashi 0:8fdf9a60065b 94
kadonotakashi 0:8fdf9a60065b 95 Thread t2(osPriorityNormal, TEST_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 96 Thread t3(osPriorityNormal, TEST_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 97
kadonotakashi 0:8fdf9a60065b 98 t2.start(callback(test_thread, &t2_delay));
kadonotakashi 0:8fdf9a60065b 99 t3.start(callback(test_thread, &t3_delay));
kadonotakashi 0:8fdf9a60065b 100
kadonotakashi 0:8fdf9a60065b 101 while (true) {
kadonotakashi 0:8fdf9a60065b 102 // Thread 1 action
kadonotakashi 0:8fdf9a60065b 103 Thread::wait(t1_delay);
kadonotakashi 0:8fdf9a60065b 104 manipulate_protected_zone(t1_delay);
kadonotakashi 0:8fdf9a60065b 105
kadonotakashi 0:8fdf9a60065b 106 core_util_critical_section_enter();
kadonotakashi 0:8fdf9a60065b 107 if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) {
kadonotakashi 0:8fdf9a60065b 108 core_util_critical_section_exit();
kadonotakashi 0:8fdf9a60065b 109 t2.terminate();
kadonotakashi 0:8fdf9a60065b 110 t3.terminate();
kadonotakashi 0:8fdf9a60065b 111 break;
kadonotakashi 0:8fdf9a60065b 112 }
kadonotakashi 0:8fdf9a60065b 113 core_util_critical_section_exit();
kadonotakashi 0:8fdf9a60065b 114 }
kadonotakashi 0:8fdf9a60065b 115
kadonotakashi 0:8fdf9a60065b 116 TEST_ASSERT_EQUAL(false, mutex_defect);
kadonotakashi 0:8fdf9a60065b 117 }
kadonotakashi 0:8fdf9a60065b 118
kadonotakashi 0:8fdf9a60065b 119 void test_dual_thread_nolock_lock_thread(Mutex *mutex)
kadonotakashi 0:8fdf9a60065b 120 {
kadonotakashi 0:8fdf9a60065b 121 osStatus stat;
kadonotakashi 0:8fdf9a60065b 122 mutex->lock();
kadonotakashi 0:8fdf9a60065b 123
kadonotakashi 0:8fdf9a60065b 124 mutex->unlock();
kadonotakashi 0:8fdf9a60065b 125 }
kadonotakashi 0:8fdf9a60065b 126
kadonotakashi 0:8fdf9a60065b 127 void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
kadonotakashi 0:8fdf9a60065b 128 {
kadonotakashi 0:8fdf9a60065b 129 bool stat_b = mutex->trylock();
kadonotakashi 0:8fdf9a60065b 130 TEST_ASSERT_EQUAL(true, stat_b);
kadonotakashi 0:8fdf9a60065b 131
kadonotakashi 0:8fdf9a60065b 132 mutex->unlock();
kadonotakashi 0:8fdf9a60065b 133 }
kadonotakashi 0:8fdf9a60065b 134
kadonotakashi 0:8fdf9a60065b 135 /** Test dual thread no-lock
kadonotakashi 0:8fdf9a60065b 136
kadonotakashi 0:8fdf9a60065b 137 Test dual thread second thread lock
kadonotakashi 0:8fdf9a60065b 138 Given two threads A & B and a mutex
kadonotakashi 0:8fdf9a60065b 139 When thread A creates a mutex and starts thread B
kadonotakashi 0:8fdf9a60065b 140 and thread B calls @a lock and @a unlock
kadonotakashi 0:8fdf9a60065b 141 Then @a lock and @a unlock operations are successfully performed.
kadonotakashi 0:8fdf9a60065b 142
kadonotakashi 0:8fdf9a60065b 143 Test dual thread second thread trylock
kadonotakashi 0:8fdf9a60065b 144 Given two threads A & B and a mutex
kadonotakashi 0:8fdf9a60065b 145 When thread A creates a mutex and starts thread B
kadonotakashi 0:8fdf9a60065b 146 and thread B calls @a trylock and @a unlock
kadonotakashi 0:8fdf9a60065b 147 Then @a trylock and @a unlock operations are successfully performed.
kadonotakashi 0:8fdf9a60065b 148 */
kadonotakashi 0:8fdf9a60065b 149 template <void (*F)(Mutex *)>
kadonotakashi 0:8fdf9a60065b 150 void test_dual_thread_nolock(void)
kadonotakashi 0:8fdf9a60065b 151 {
kadonotakashi 0:8fdf9a60065b 152 Mutex mutex;
kadonotakashi 0:8fdf9a60065b 153 Thread thread(osPriorityNormal, TEST_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 154
kadonotakashi 0:8fdf9a60065b 155 thread.start(callback(F, &mutex));
kadonotakashi 0:8fdf9a60065b 156
kadonotakashi 0:8fdf9a60065b 157 wait_ms(TEST_DELAY);
kadonotakashi 0:8fdf9a60065b 158 }
kadonotakashi 0:8fdf9a60065b 159
kadonotakashi 0:8fdf9a60065b 160 void test_dual_thread_lock_unlock_thread(Mutex *mutex)
kadonotakashi 0:8fdf9a60065b 161 {
kadonotakashi 0:8fdf9a60065b 162 mutex->lock();
kadonotakashi 0:8fdf9a60065b 163 }
kadonotakashi 0:8fdf9a60065b 164
kadonotakashi 0:8fdf9a60065b 165 /** Test dual thread lock unlock
kadonotakashi 0:8fdf9a60065b 166
kadonotakashi 0:8fdf9a60065b 167 Given two threads and a lock
kadonotakashi 0:8fdf9a60065b 168 When thread A locks the lock and starts thread B
kadonotakashi 0:8fdf9a60065b 169 and thread B calls @a lock on the mutex
kadonotakashi 0:8fdf9a60065b 170 Then thread B waits for thread A to unlock the lock
kadonotakashi 0:8fdf9a60065b 171 When thread A calls @a unlock on the mutex
kadonotakashi 0:8fdf9a60065b 172 Then thread B acquires the lock
kadonotakashi 0:8fdf9a60065b 173 */
kadonotakashi 0:8fdf9a60065b 174 void test_dual_thread_lock_unlock(void)
kadonotakashi 0:8fdf9a60065b 175 {
kadonotakashi 0:8fdf9a60065b 176 Mutex mutex;
kadonotakashi 0:8fdf9a60065b 177 osStatus stat;
kadonotakashi 0:8fdf9a60065b 178 Thread thread(osPriorityNormal, TEST_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 179
kadonotakashi 0:8fdf9a60065b 180 mutex.lock();
kadonotakashi 0:8fdf9a60065b 181
kadonotakashi 0:8fdf9a60065b 182 thread.start(callback(test_dual_thread_lock_unlock_thread, &mutex));
kadonotakashi 0:8fdf9a60065b 183
kadonotakashi 0:8fdf9a60065b 184 mutex.unlock();
kadonotakashi 0:8fdf9a60065b 185
kadonotakashi 0:8fdf9a60065b 186 wait_ms(TEST_DELAY);
kadonotakashi 0:8fdf9a60065b 187 }
kadonotakashi 0:8fdf9a60065b 188
kadonotakashi 0:8fdf9a60065b 189 void test_dual_thread_lock_trylock_thread(Mutex *mutex)
kadonotakashi 0:8fdf9a60065b 190 {
kadonotakashi 0:8fdf9a60065b 191 bool stat = mutex->trylock();
kadonotakashi 0:8fdf9a60065b 192 TEST_ASSERT_EQUAL(false, stat);
kadonotakashi 0:8fdf9a60065b 193 }
kadonotakashi 0:8fdf9a60065b 194
kadonotakashi 0:8fdf9a60065b 195 void test_dual_thread_lock_lock_thread(Mutex *mutex)
kadonotakashi 0:8fdf9a60065b 196 {
kadonotakashi 0:8fdf9a60065b 197 Timer timer;
kadonotakashi 0:8fdf9a60065b 198 timer.start();
kadonotakashi 0:8fdf9a60065b 199
kadonotakashi 0:8fdf9a60065b 200 bool stat = mutex->trylock_for(TEST_DELAY);
kadonotakashi 0:8fdf9a60065b 201 TEST_ASSERT_EQUAL(false, stat);
kadonotakashi 0:8fdf9a60065b 202 TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, timer.read_us());
kadonotakashi 0:8fdf9a60065b 203 }
kadonotakashi 0:8fdf9a60065b 204
kadonotakashi 0:8fdf9a60065b 205 /** Test dual thread lock
kadonotakashi 0:8fdf9a60065b 206
kadonotakashi 0:8fdf9a60065b 207 Test dual thread lock locked
kadonotakashi 0:8fdf9a60065b 208 Given a mutex and two threads A & B
kadonotakashi 0:8fdf9a60065b 209 When thread A calls @a lock and starts thread B
kadonotakashi 0:8fdf9a60065b 210 and thread B calls @a lock with 500ms timeout
kadonotakashi 0:8fdf9a60065b 211 Then thread B waits 500ms and timeouts
kadonotakashi 0:8fdf9a60065b 212
kadonotakashi 0:8fdf9a60065b 213 Test dual thread trylock locked
kadonotakashi 0:8fdf9a60065b 214 Given a mutex and two threads A & B
kadonotakashi 0:8fdf9a60065b 215 When thread A calls @a lock and starts thread B
kadonotakashi 0:8fdf9a60065b 216 Then thread B calls @a trylock
kadonotakashi 0:8fdf9a60065b 217 and thread B fails to acquire the lock
kadonotakashi 0:8fdf9a60065b 218 */
kadonotakashi 0:8fdf9a60065b 219 template <void (*F)(Mutex *)>
kadonotakashi 0:8fdf9a60065b 220 void test_dual_thread_lock(void)
kadonotakashi 0:8fdf9a60065b 221 {
kadonotakashi 0:8fdf9a60065b 222 Mutex mutex;
kadonotakashi 0:8fdf9a60065b 223 osStatus stat;
kadonotakashi 0:8fdf9a60065b 224 Thread thread(osPriorityNormal, TEST_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 225
kadonotakashi 0:8fdf9a60065b 226 mutex.lock();
kadonotakashi 0:8fdf9a60065b 227
kadonotakashi 0:8fdf9a60065b 228 thread.start(callback(F, &mutex));
kadonotakashi 0:8fdf9a60065b 229
kadonotakashi 0:8fdf9a60065b 230 wait_ms(TEST_LONG_DELAY);
kadonotakashi 0:8fdf9a60065b 231
kadonotakashi 0:8fdf9a60065b 232 mutex.unlock();
kadonotakashi 0:8fdf9a60065b 233 }
kadonotakashi 0:8fdf9a60065b 234
kadonotakashi 0:8fdf9a60065b 235 /** Test single thread lock recursive
kadonotakashi 0:8fdf9a60065b 236
kadonotakashi 0:8fdf9a60065b 237 Given a mutex and a single running thread
kadonotakashi 0:8fdf9a60065b 238 When thread calls @a lock twice and @a unlock twice on the mutex
kadonotakashi 0:8fdf9a60065b 239 Then @a lock and @a unlock operations are successfully performed.
kadonotakashi 0:8fdf9a60065b 240 */
kadonotakashi 0:8fdf9a60065b 241 void test_single_thread_lock_recursive(void)
kadonotakashi 0:8fdf9a60065b 242 {
kadonotakashi 0:8fdf9a60065b 243 Mutex mutex;
kadonotakashi 0:8fdf9a60065b 244 osStatus stat;
kadonotakashi 0:8fdf9a60065b 245
kadonotakashi 0:8fdf9a60065b 246 mutex.lock();
kadonotakashi 0:8fdf9a60065b 247
kadonotakashi 0:8fdf9a60065b 248 mutex.lock();
kadonotakashi 0:8fdf9a60065b 249
kadonotakashi 0:8fdf9a60065b 250 mutex.unlock();
kadonotakashi 0:8fdf9a60065b 251
kadonotakashi 0:8fdf9a60065b 252 mutex.unlock();
kadonotakashi 0:8fdf9a60065b 253 }
kadonotakashi 0:8fdf9a60065b 254
kadonotakashi 0:8fdf9a60065b 255 /** Test single thread trylock
kadonotakashi 0:8fdf9a60065b 256
kadonotakashi 0:8fdf9a60065b 257 Given a mutex and a single running thread
kadonotakashi 0:8fdf9a60065b 258 When thread calls @a trylock and @a unlock on the mutex
kadonotakashi 0:8fdf9a60065b 259 Then @a trylock and @a unlock operations are successfully performed.
kadonotakashi 0:8fdf9a60065b 260 */
kadonotakashi 0:8fdf9a60065b 261 void test_single_thread_trylock(void)
kadonotakashi 0:8fdf9a60065b 262 {
kadonotakashi 0:8fdf9a60065b 263 Mutex mutex;
kadonotakashi 0:8fdf9a60065b 264
kadonotakashi 0:8fdf9a60065b 265 bool stat_b = mutex.trylock();
kadonotakashi 0:8fdf9a60065b 266 TEST_ASSERT_EQUAL(true, stat_b);
kadonotakashi 0:8fdf9a60065b 267
kadonotakashi 0:8fdf9a60065b 268 mutex.unlock();
kadonotakashi 0:8fdf9a60065b 269 }
kadonotakashi 0:8fdf9a60065b 270
kadonotakashi 0:8fdf9a60065b 271 /** Test single thread lock
kadonotakashi 0:8fdf9a60065b 272
kadonotakashi 0:8fdf9a60065b 273 Given a mutex and a single running thread
kadonotakashi 0:8fdf9a60065b 274 When thread calls @a lock and @a unlock on the mutex
kadonotakashi 0:8fdf9a60065b 275 Then @a lock and @a unlock operations are successfully performed.
kadonotakashi 0:8fdf9a60065b 276 */
kadonotakashi 0:8fdf9a60065b 277 void test_single_thread_lock(void)
kadonotakashi 0:8fdf9a60065b 278 {
kadonotakashi 0:8fdf9a60065b 279 Mutex mutex;
kadonotakashi 0:8fdf9a60065b 280 osStatus stat;
kadonotakashi 0:8fdf9a60065b 281
kadonotakashi 0:8fdf9a60065b 282 mutex.lock();
kadonotakashi 0:8fdf9a60065b 283
kadonotakashi 0:8fdf9a60065b 284 mutex.unlock();
kadonotakashi 0:8fdf9a60065b 285 }
kadonotakashi 0:8fdf9a60065b 286
kadonotakashi 0:8fdf9a60065b 287 utest::v1::status_t test_setup(const size_t number_of_cases)
kadonotakashi 0:8fdf9a60065b 288 {
kadonotakashi 0:8fdf9a60065b 289 GREENTEA_SETUP(10, "default_auto");
kadonotakashi 0:8fdf9a60065b 290 return verbose_test_setup_handler(number_of_cases);
kadonotakashi 0:8fdf9a60065b 291 }
kadonotakashi 0:8fdf9a60065b 292
kadonotakashi 0:8fdf9a60065b 293 Case cases[] = {
kadonotakashi 0:8fdf9a60065b 294 Case("Test single thread lock", test_single_thread_lock),
kadonotakashi 0:8fdf9a60065b 295 Case("Test single thread trylock", test_single_thread_trylock),
kadonotakashi 0:8fdf9a60065b 296 Case("Test single thread lock recursive", test_single_thread_lock_recursive),
kadonotakashi 0:8fdf9a60065b 297 Case("Test dual thread lock locked", test_dual_thread_lock<test_dual_thread_lock_lock_thread>),
kadonotakashi 0:8fdf9a60065b 298 Case("Test dual thread trylock locked", test_dual_thread_lock<test_dual_thread_lock_trylock_thread>),
kadonotakashi 0:8fdf9a60065b 299 Case("Test dual thread lock unlock", test_dual_thread_lock_unlock),
kadonotakashi 0:8fdf9a60065b 300 Case("Test dual thread second thread lock", test_dual_thread_nolock<test_dual_thread_nolock_lock_thread>),
kadonotakashi 0:8fdf9a60065b 301 Case("Test dual thread second thread trylock", test_dual_thread_nolock<test_dual_thread_nolock_trylock_thread>),
kadonotakashi 0:8fdf9a60065b 302 Case("Test multiple thread", test_multiple_threads),
kadonotakashi 0:8fdf9a60065b 303 };
kadonotakashi 0:8fdf9a60065b 304
kadonotakashi 0:8fdf9a60065b 305 Specification specification(test_setup, cases);
kadonotakashi 0:8fdf9a60065b 306
kadonotakashi 0:8fdf9a60065b 307 int main()
kadonotakashi 0:8fdf9a60065b 308 {
kadonotakashi 0:8fdf9a60065b 309 return !Harness::run(specification);
kadonotakashi 0:8fdf9a60065b 310 }