Precise time sync (ms) between multiple Photons

I’m working on a “stopwatch” based on multiple photons. I need them to be exact synchronized (within 10-20 ms). I might not have internet connection, but they will all be on local wifi.
I have thought about synchronizing time from a master unit (raspberry or greater), but as distance to master may varies and there is different network latency I don’t think this will work.
Instead I’m thinking to connect a GPS module to each Photon. Is it possible to set the integrated RTC with time from the GPS unit with that precision and later read the time including ms from the Photon?

The different time stamps will be transmitted via Wifi to a database on the master unit.
Any suggestions or do I need a more sofisticated uP?

@lubker - I have been working on proving out the instructions for running the local cloud on a Raspberry Pi 3 setting that up as an access point. I finally have it all working and can say that Photons do a time sync against the local cloud. I don’t know what sort of latency you will have between the Photon and RPi3.

I am using the stock spark-server and spark-protocol. There is one small patch to perform in the spark-protocol code noted in my instructions. There is a lot of patches floating out there. At this point it is sufficient for the device to connect to the local cloud and obtain the cloud time – from the RPi3.

$ particle serial monitor --follow
Polling for available serial device...
Opening serial monitor for com port: "/dev/cu.usbmodem1411"
Serial monitor opened successfully:
0000001922 [system] INFO: ARM_WLAN_WD 2
0000001922 [hal.wlan] INFO: Bringing WiFi interface up with DHCP
0000002974 [system] INFO: CLR_WLAN_WD 1, DHCP success
0000002975 [system] INFO: Cloud: connecting
0000002976 [system] INFO: Read Server Address = type:0,domain:,ip:, port: 65535
0000005732 [system] INFO: connected to cloud
0000005732 [system] INFO: Cloud socket connected
0000005732 [system] INFO: Starting handshake: presense_announce=1
0000005733 [comm.sparkprotocol.handshake] INFO: Started: Receive nonce
0000005740 [comm.sparkprotocol.handshake] INFO: Encrypting handshake nonce
0000005786 [comm.sparkprotocol.handshake] INFO: Sending encrypted nonce
0000005787 [comm.sparkprotocol.handshake] INFO: Receive key
0000005878 [comm.sparkprotocol.handshake] INFO: Setting key
0000006066 [comm.sparkprotocol.handshake] INFO: Sending HELLO message
0000006067 [comm.sparkprotocol.handshake] INFO: Receiving HELLO response
0000006078 [comm.sparkprotocol.handshake] INFO: Completed
0000006078 [system] INFO: Send spark/device/claim/code event
0000006079 [system] INFO: Send spark/hardware/max_binary event
0000006079 [system] INFO: spark/hardware/ota_chunk_size event
0000006079 [system] INFO: Send spark/device/last_reset event
0000006080 [system] INFO: Send subscriptions
0000006080 [comm.sparkprotocol] INFO: Sending TIME request
0000006082 [system] INFO: Cloud connected
0000009583 [comm.sparkprotocol] INFO: Received TIME response: 1502647946

My version of the local cloud installation instructions and AP instructions can be found here: