[BUG] Poke should use volatile.
Hi. I think poke function should use volatile on C language side. If not, the code created with jhc cannot write raw memory. diff --git a/src/C/FromGrin2.hs b/src/C/FromGrin2.hs index 46e1a08..d4508bd 100644 --- a/src/C/FromGrin2.hs +++ b/src/C/FromGrin2.hs @@ -712,7 +712,7 @@ convertPrim p vs ty | (Poke t) <- p, [v,x] <- vs = do v' <- convertVal v x' <- convertVal x - return $ expressionRaw ("*((" <> (opTyToC' t) <+> "*)" <> (parens $ renderG v') <> text ") = " <> renderG x') + return $ expressionRaw ("*((volatile " <> (opTyToC' t) <+> "*)" <> (parens $ renderG v') <> text ") = " <> renderG x') | (AddrOf _ t) <- p, [] <- vs = do rt <- convertTypes ty return . cast rt $ expressionRaw ('&':unpackPS t) I found it when use jhc to program Cortex-M3. https://gitorious.org/metasepi/demo-cortex-m3 Regards, -- Kiwamu Okabe
What do you mean by raw memory? I don't think the volatile should be
needed in general for C allocated variables, but perhaps you are
writing to hardware registers?
John
On Fri, Feb 22, 2013 at 5:11 AM, Kiwamu Okabe
Hi.
I think poke function should use volatile on C language side. If not, the code created with jhc cannot write raw memory.
diff --git a/src/C/FromGrin2.hs b/src/C/FromGrin2.hs index 46e1a08..d4508bd 100644 --- a/src/C/FromGrin2.hs +++ b/src/C/FromGrin2.hs @@ -712,7 +712,7 @@ convertPrim p vs ty | (Poke t) <- p, [v,x] <- vs = do v' <- convertVal v x' <- convertVal x - return $ expressionRaw ("*((" <> (opTyToC' t) <+> "*)" <> (parens $ renderG v') <> text ") = " <> renderG x') + return $ expressionRaw ("*((volatile " <> (opTyToC' t) <+> "*)" <> (parens $ renderG v') <> text ") = " <> renderG x') | (AddrOf _ t) <- p, [] <- vs = do rt <- convertTypes ty return . cast rt $ expressionRaw ('&':unpackPS t)
I found it when use jhc to program Cortex-M3.
https://gitorious.org/metasepi/demo-cortex-m3
Regards, -- Kiwamu Okabe
_______________________________________________ jhc mailing list jhc@haskell.org http://www.haskell.org/mailman/listinfo/jhc
Hi John.
On Wed, Mar 6, 2013 at 10:06 PM, John Meacham
What do you mean by raw memory? I don't think the volatile should be needed in general for C allocated variables, but perhaps you are writing to hardware registers?
Yes. I would like to write to hardware registers. https://github.com/ajhc/demo-cortex-m3/blob/master/stbee-mini/hs_src/Main_si... We can do real programming with pure Haskell code, if poke function is used. Best regards, -- Kiwamu Okabe
Interesting. Perhaps something like
foreign import "volatile &periphBase" :: Ptr Word32
which will declare
extern volatile uint32_t periphBase in the file, then you would just
have a linker symbol periphBase at 0x4000000. (or just import a value
with zero and do pointer arithmetic like you do)
John
On Wed, Mar 6, 2013 at 6:05 AM, Kiwamu Okabe
Hi John.
On Wed, Mar 6, 2013 at 10:06 PM, John Meacham
wrote: What do you mean by raw memory? I don't think the volatile should be needed in general for C allocated variables, but perhaps you are writing to hardware registers?
Yes. I would like to write to hardware registers.
https://github.com/ajhc/demo-cortex-m3/blob/master/stbee-mini/hs_src/Main_si...
We can do real programming with pure Haskell code, if poke function is used.
Best regards, -- Kiwamu Okabe
_______________________________________________ jhc mailing list jhc@haskell.org http://www.haskell.org/mailman/listinfo/jhc
Hi, John.
On Wed, Mar 6, 2013 at 11:17 PM, John Meacham
Interesting. Perhaps something like
foreign import "volatile &periphBase" :: Ptr Word32
which will declare
extern volatile uint32_t periphBase in the file, then you would just have a linker symbol periphBase at 0x4000000. (or just import a value with zero and do pointer arithmetic like you do)
Ah. It's nice for Cortex-M3! But I would like to rewrite NetBSD kernel with jhc and Haskell code. http://netbsdman.masterq.net/org_netbsd/src/share/man/man9/bus_space.9.html NetBSD doesn't touch raw memory directly. It has own bus driver. I would like to rewrite the bus driver with jhc. How do I write the code with extern volatile style? Thank's, -- Kiwamu Okabe
On Wed, Mar 6, 2013 at 6:43 AM, Kiwamu Okabe
How do I write the code with extern volatile style?
As a quick test that won't require modifying jhc, add extern volatile void physicalAddress; to your rts header and compile adding the flag "-Wl,--defsym=physicalAddress=0" then in your haskell code where you want to do hardware register access do foreign import "&physicalAddress" physicalAddress :: Ptr Word32 and use physicalAddress instead of nullPtr in your code as the base, by going through the volatile physicalAddress it will know not to optimize it away, whereas it knows that 'nullPtr' is actually zero which is why it was causing issues. So you would have periphBase = physicalAddress `plusPtr` 0x40000000 then you won't have to modify the poke and peek primitives. John
okay figured out a cleaner way to do it.
include the attached header file and add the arm-addresses.lds file to
the gcc or ld command line. Then you can foreign import the pointers.
If you can verify this works then I can implement it as part of the
ForeignData proposal with a volatile extension and have the compiler
automatically take these steps.
http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignData
so if you do this
foreign import "volatile &periphBase" periphBase :: Ptr a = 0x40000000
it will automatically create the appropriate header and lds entries.
John
On Wed, Mar 6, 2013 at 7:05 AM, John Meacham
On Wed, Mar 6, 2013 at 6:43 AM, Kiwamu Okabe
wrote: How do I write the code with extern volatile style?
As a quick test that won't require modifying jhc, add
extern volatile void physicalAddress; to your rts header and compile adding the flag "-Wl,--defsym=physicalAddress=0"
then in your haskell code where you want to do hardware register access do
foreign import "&physicalAddress" physicalAddress :: Ptr Word32
and use physicalAddress instead of nullPtr in your code as the base, by going through the volatile physicalAddress it will know not to optimize it away, whereas it knows that 'nullPtr' is actually zero which is why it was causing issues. So you would have
periphBase = physicalAddress `plusPtr` 0x40000000
then you won't have to modify the poke and peek primitives.
John
Hi John.
On Thu, Mar 7, 2013 at 7:59 AM, John Meacham
include the attached header file and add the arm-addresses.lds file to the gcc or ld command line. Then you can foreign import the pointers.
If you can verify this works then I can implement it as part of the ForeignData proposal with a volatile extension and have the compiler automatically take these steps.
http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignData
so if you do this foreign import "volatile &periphBase" periphBase :: Ptr a = 0x40000000
it will automatically create the appropriate header and lds entries.
I tried this method and running test is green. But I have some question on C code outputted with Ajhc. Is it correct to cast volatile pointer with (uint16_t *)? --- hs_main.c static wptr_t A_STD A_MALLOC fW$__fMain_ledOff(gc_t gc,uint16_t v1167729185) { *((uint16_t *)((uintptr_t)&jhc_phys_brrPtr)) = v1167729185; return SET_RAW_TAG(CJhc_Prim_Prim_$LR); } --------- I have same success result running with below C header. --- stm32f3-discovery/jhc_custom/rts/jhc_rts_header.h extern void jhc_phys_brrPtr; extern void jhc_phys_bsrrPtr; // without volatile ------- Best regards, -- Kiwamu Okabe
I belive it is okay because the 'casted' non-volatile pointer is only
used once. as in, there is never a non-volatile version of the pointer
that is used in more than one place that the compiler might try to
optimize out. Each use jhc will generate code that creates the pointer
relative to the volatile physicalAddr so it won't be able to merge
them.
John
On Wed, Mar 6, 2013 at 10:07 PM, Kiwamu Okabe
Hi John.
On Thu, Mar 7, 2013 at 7:59 AM, John Meacham
wrote: include the attached header file and add the arm-addresses.lds file to the gcc or ld command line. Then you can foreign import the pointers.
If you can verify this works then I can implement it as part of the ForeignData proposal with a volatile extension and have the compiler automatically take these steps.
http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignData
so if you do this foreign import "volatile &periphBase" periphBase :: Ptr a = 0x40000000
it will automatically create the appropriate header and lds entries.
I tried this method and running test is green. But I have some question on C code outputted with Ajhc. Is it correct to cast volatile pointer with (uint16_t *)?
--- hs_main.c static wptr_t A_STD A_MALLOC fW$__fMain_ledOff(gc_t gc,uint16_t v1167729185) { *((uint16_t *)((uintptr_t)&jhc_phys_brrPtr)) = v1167729185; return SET_RAW_TAG(CJhc_Prim_Prim_$LR); } ---------
I have same success result running with below C header.
--- stm32f3-discovery/jhc_custom/rts/jhc_rts_header.h extern void jhc_phys_brrPtr; extern void jhc_phys_bsrrPtr; // without volatile -------
Best regards, -- Kiwamu Okabe
_______________________________________________ jhc mailing list jhc@haskell.org http://www.haskell.org/mailman/listinfo/jhc
Hi John.
On Thu, Mar 7, 2013 at 5:47 PM, John Meacham
I belive it is okay because the 'casted' non-volatile pointer is only used once. as in, there is never a non-volatile version of the pointer that is used in more than one place that the compiler might try to optimize out. Each use jhc will generate code that creates the pointer relative to the volatile physicalAddr so it won't be able to merge them.
Ah. It's good news for me. I understand that poke function spec isn't BUG. I will rewrite Cortex-M3 demo with extern_volatile.patch style. And Ajhc's volatile patch should be dropped. In my use case, ForeignData style doesn't be needed. Thank you for your time. -- Kiwamu Okabe
Hi.
On Thu, Mar 7, 2013 at 6:24 PM, Kiwamu Okabe
Ah. It's good news for me. I understand that poke function spec isn't BUG.
I will rewrite Cortex-M3 demo with extern_volatile.patch style. And Ajhc's volatile patch should be dropped. In my use case, ForeignData style doesn't be needed.
Just one last thing. The style is good for peek function? It's expected that reading the register is read twice by peek-ing same address by Haskell code twice. Best regards, -- Kiwamu Okabe
Hi, John.
Thank's for your advice.
On Thu, Mar 7, 2013 at 12:05 AM, John Meacham
As a quick test that won't require modifying jhc, add
extern volatile void physicalAddress; to your rts header and compile adding the flag "-Wl,--defsym=physicalAddress=0"
then in your haskell code where you want to do hardware register access do
foreign import "&physicalAddress" physicalAddress :: Ptr Word32
and use physicalAddress instead of nullPtr in your code as the base, by going through the volatile physicalAddress it will know not to optimize it away, whereas it knows that 'nullPtr' is actually zero which is why it was causing issues. So you would have
periphBase = physicalAddress `plusPtr` 0x40000000
then you won't have to modify the poke and peek primitives.
It's good. My application controls memory mapped IO with the patch extern_volatile.patch (attached). But I have more question. Ajhc with your patch outputs hs_main.c file (attached) from Main.hs file (attached). --- In hs_main.c static wptr_t A_STD A_MALLOC fW$__fMain_ledOff(gc_t gc,uint16_t v691543073) { *((uint16_t *)(1207963688 + ((uintptr_t)&jhc_physicalAddress))) = v691543073; return SET_RAW_TAG(CJhc_Prim_Prim_$LR); } -------- It casts &jhc_physicalAddress with uintptr_t. Does it strip the volatile type? If not, extern volatile method resolves my problem perfectly. Thank's. -- Kiwamu Okabe
participants (2)
-
John Meacham -
Kiwamu Okabe